이 글에서는 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
댓글
댓글 쓰기