기본 콘텐츠로 건너뛰기

DDNS(Dynamic DNS) 서버 만들기

이 글에서는 PowerDNS를 사용하여 DDNS를 만드는 방법에 대해 설명한다.

PowerDNS의 예전 버젼에서는 recursive 처리가 포함되어 있었지만, 보안의 이유로 Authoritative Server와  Recursor로 분리되었다.

Authoritative Server가 외부에서 요청되는 query에 대해 응답하는 용도로 사용되며, 여기서는 Authoritative Server를 통해 DDNS 서버를 만드는 방법을 정리한다.


설치

https://repo.powerdns.com/에 설치관련 내용이 정리되어 있다.
Ubuntu 16.04기준으로, 4.4.x version의 설치 방법을 보면, 다음의 방법으로 설치할 수 있다.

Create the file '/etc/apt/sources.list.d/pdns.list' with this content:

deb [arch=amd64] http://repo.powerdns.com/ubuntu xenial-auth-44 main

And this to '/etc/apt/preferences.d/pdns':

Package: pdns-*
Pin: origin repo.powerdns.com
Pin-Priority: 600

and execute the following commands:

curl https://repo.powerdns.com/FD380FBB-pub.asc | sudo apt-key add - &&
sudo apt-get update &&
sudo apt-get install pdns-server

MySQL 연동

1. MySQL backend 설치

MySQL backend 를 다음과 같이 설치한다.
sudo apt-get install pdns-backend-mysql

/etc/powerdns/pdns.conf 파일에 다음과 같은 내용을 작성한다.

launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=powerdns_user
gmysql-dbname=powerdns
gmysql-password=비밀번호
launch를 제외한 내용은 설치 상태에 맞추어 작성해야 한다.

2. DB 만들기

pdns.conf파일에 작성한 내용대로 
 - 사용자 생성
 - DB 생성
 - 사용자에게 DB의 모든 table에 대한 권한 주기
를 수행한다.

mysql> create user 'powerdns_user'@'localhost' identified by '비밀번호';
mysql> create database powerdns;

mysql> grant all on powerdns.* to powerdns_user@localhost identified by ‘비’;

mysql> use powerdns;


그후, 이곳의 내용에 따라 Table을 생성한다. 내용은 다음과 같다.
CREATE TABLE domains (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255) NOT NULL,
  master                VARCHAR(128) DEFAULT NULL,
  last_check            INT DEFAULT NULL,
  type                  VARCHAR(6) NOT NULL,
  notified_serial       INT UNSIGNED DEFAULT NULL,
  account               VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';

CREATE UNIQUE INDEX name_index ON domains(name);


CREATE TABLE records (
  id                    BIGINT AUTO_INCREMENT,
  domain_id             INT DEFAULT NULL,
  name                  VARCHAR(255) DEFAULT NULL,
  type                  VARCHAR(10) DEFAULT NULL,
  content               VARCHAR(64000) DEFAULT NULL,
  ttl                   INT DEFAULT NULL,
  prio                  INT DEFAULT NULL,
  disabled              TINYINT(1) DEFAULT 0,
  ordername             VARCHAR(255) BINARY DEFAULT NULL,
  auth                  TINYINT(1) DEFAULT 1,
  PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';

CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX ordername ON records (ordername);


CREATE TABLE supermasters (
  ip                    VARCHAR(64) NOT NULL,
  nameserver            VARCHAR(255) NOT NULL,
  account               VARCHAR(40) CHARACTER SET 'utf8' NOT NULL,
  PRIMARY KEY (ip, nameserver)
) Engine=InnoDB CHARACTER SET 'latin1';


CREATE TABLE comments (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  name                  VARCHAR(255) NOT NULL,
  type                  VARCHAR(10) NOT NULL,
  modified_at           INT NOT NULL,
  account               VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL,
  comment               TEXT CHARACTER SET 'utf8' NOT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';

CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);


CREATE TABLE domainmetadata (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  kind                  VARCHAR(32),
  content               TEXT,
  PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';

CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);


CREATE TABLE cryptokeys (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  flags                 INT NOT NULL,
  active                BOOL,
  published             BOOL DEFAULT 1,
  content               TEXT,
  PRIMARY KEY(id)
) Engine=InnoDB CHARACTER SET 'latin1';

CREATE INDEX domainidindex ON cryptokeys(domain_id);


CREATE TABLE tsigkeys (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255),
  algorithm             VARCHAR(50),
  secret                VARCHAR(255),
  PRIMARY KEY (id)
) Engine=InnoDB CHARACTER SET 'latin1';

CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);

DB에 record 추가하기

다음과 같이 필요한 record들을 records table에 추가한다.
# mysql pdnstest
mysql> INSERT INTO domains (name, type) values ('example.com', 'NATIVE');
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','localhost admin.example.com 1 10380 3600 604800 3600','SOA',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','dns-us1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','dns-eu1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'www.example.com','192.0.2.10','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'mail.example.com','192.0.2.12','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'localhost.example.com','127.0.0.1','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'example.com','mail.example.com','MX',120,25);

Domain 위임하기

가입된 domain 업체를 통해, 다음과 같이 등록을 하여 domain을 우리가 설치한 authoritative server에서 운영되도록 한다.
  • NS record
    • name : example.com
    • value : ns.example.com
    • ttl : 3600
  • A record
    • A 레코드
    • name : ns.example.com
    • value : 1.2.3.4
    • ttl : 3600

동적 IP 등록/변경

DNS control server를 만들어, 이 서버가 DB의 A record를 갱신하도록 하여 구현할 수 있다.
이 서비스를 사용하는 사용자는 자신의 IP가 변경될 때마다
- control server에 접속
- 인증 진행
- 자신의 IP 갱신
의 순서로 동적으로 IP를 변경할 수 있다.

Troubleshooting

53 port 충돌

만약 server로 사용할 host의 53 port가 충돌이 발생할 경우, 새로 설치한 dns server가 작동하지 않을 수 있다. 이전에 사용하고 있는  service(예: bind9, dnsmasq,...)가 있다면, 이들을 종료시킨후, 필요하다면, 제거하고 사용해야 한다.

dns service(예: bind9, dnsmasq,...)제거 후 외부로의 dns query가 동작하지 않을때

ubuntu의 경우 systemd-resolved가 기본 resolver로 사용된다.
하지만, 이전의 작업으로 bind9나 dnsmasq 가 설치되어 있는 경우라면, 이를 제거하는 과정에서, 외부로의 dns resolving이 안되는 경우가 발생한다.
이를 해결하기 위해 systemd-resolved를 다시 살려 줘야 한다.

  • systemctl enable systemd-resolved
  • systemctl start systemd-resolved.service





댓글

이 블로그의 인기 게시물