OpenWrt DNS 설정

보안 DNS

기본적으로 dns 쿼리는 53번 포트를 이용해 평문으로 패킷을 전송합니다. 이것은 우리가 웹브라우저를 통해 https 웹사이트에 접속하더라도 dns 쿼리는 여전히 53번포트를 이용해 암호화하지 않고 평문으로 전송되기 때문에 노출되게 되며 정부나 포털, 광고주 또는 악의적인 사람들은 사용자의 접속 정보를 추적하고 수집할 수 있습니다.

이러한 개인 프라이버시 침해를 방지하기 위해 dns 쿼리 및 응답을 평문이 아닌 암호화하기 위해 개발된 표준이 DNS over TLS (DoT)와 DNS over Https (DoH)입니다.

각 표준은 개별로 개발되었으며 RFC 표준이 따로 존재하지만 가장 큰 차이점은 사용하는 포트가 다르다고 보면 됩니다.

구분DNS over TLS (DoT)DNS over HTTPS (DoH)
IETFRFC 7858, 8310RFC 8484
포트853 (고정)443 (가변)
layertransport layerapplication layer
특징사용자 차원에서는 dns 쿼리 및 응답은 암호화 하지만
전용포트를 사용하므로 tls를 통한dns를 사용한다는 것을 알 수 있으므로 차단할 수 있으나
네트워크 관리 차원에서는 전용포트를 사용하므로 악성 트래픽을 차단하거나 모니터링 할 수 있으므로 유용
DoH 쿼리는 일반 https 트래픽에 숨겨져 있으므로 다른 모든 https 트래픽도 차단하지 않고는 쉽게 차단할 수 없어 사용자에게는 더 많은 개인정보보호
네트워크 계층 차이로 인한 많은 코딩, 라이브러리 필요하고
패킷 크기가 DoT보다 크며
약간 더 긴 지연시간 발생
참고google, mozilla 같은 브라우저로 먹고사는 회사에서 밀고 있음

참고로 DoT나 DoH 둘 중에 하나만 설치하면 되며, 먼저 DoT 다음은 DoH 설치방법을 설명합니다.

OpenWrt에 stubby 사용하기 (DoT)

opkg update
opkg install stubby ca-bundle

/etc/config/stubby를 다음과 편집합니다.

  • ipv4 루프백 인터페이스의 포트 5453에서 stubby가 수신하도록합니다. (127.0.0.1#5453)
  • ipv6은 주석처리 합니다. (현재 국내 isp는 ipv6 서비스를 하지 않습니다.) (0::1@5453)
  • option manual '1'로 설정하면 /etc/config/stubby의 설정은 모두 무시하고 원래 stubby 설정화일인 json 형식의 /etc/stubby/stubby.yml 화일을 설정화일로 인식하여 서비스를 구동하게 되며, option manual '0'으로 설정하면 OpenWrt 통합설정인터페이스인 uci 형식의 /etc/config/stubby로 설정을 구성하고 서비스를 구동합니다. 아래 구성은 uci를 통한 구성의 예입니다.(json 형식이 원래 stubby의 설정화일이라 그런지 좀 더 정교한 설정이 가능하다고 하는데 사실 uci 형식과 구성의 차이는 없습니다.)
  • 본 예제처럼 upstream resolver는 cloudflare dns 1.1.1.1 및 1.0.0.1을 사용할 경우 idle_time을 9000으로 설정합니다.
config stubby 'global'
        option manual '0'
        option trigger 'wan'
        option triggerdelay '2'
        list dns_transport 'GETDNS_TRANSPORT_TLS'
        option tls_authentication '1'
        option tls_query_padding_blocksize '128'
        option appdata_dir '/var/lib/stubby'
        option edns_client_subnet_private '1'
        option idle_timeout '9000'
        option round_robin_upstreams '1'
        list listen_address '127.0.0.1@5453'
#       list listen_address '0::1@5453'
        option tls_min_version '1.3'
#       option tls_max_version '1.3'

# Upstream resolvers are specified using 'resolver' sections.
config resolver
        option address '1.1.1.1'
        option tls_auth_name 'cloudflare-dns.com'

config resolver
        option address '1.0.0.1'
        option tls_auth_name 'cloudflare-dns.com'

/etc/config/network를 다음을 추가 및 편집합니다. 그리고 설정하는 김에 ipv6 대한 설정을 죽입니다.

...
config interface 'lan'
        ...
        option ipv6 '0'
        option delegate '0'

config interface 'wan'
        ...
        option peerdns '0'
        option dns '127.0.0.1'
        option ipv6 '0'
        option delegate '0'

config interface 'wan6'
        ...
        option peerdns '0'
 #      option dns '0::1'
        option ipv6 '0'
        option delegate '0'
        option auto '0'
...

dnssec 사용을 위해 dnsmasq패키지를 제거하고 dnsmasq-full 패키지를 설치합니다.

opkg install dnsmasq-full --download-only && opkg remove dnsmasq && opkg install dnsmasq-full --cache . && rm *.ipk

/etc/config/dhcp를 다음과 같이 추가 및 편집합니다.

config dnsmasq
        ...
        option noresolv '1'
        option dnssec '1'
        option dnsseccheckunsigned '1'
        list server '127.0.0.1#5453'
#       list server '0::1#5453'
        list server '/openwrt.pool.ntp.org/1.1.1.1'

config dhcp 'lan'
        ...
        option dhcpv4 'server'
        option dhcpv6 'disabled'
        list ra_flags 'none'

config dhcp 'wan'
        ...
        option ignore '1'
        list ra_flags 'none'

config dhcp 'wan6'
        ....
        option ignore '1'
        list ra_flags 'none'
...

서비스 재시작 (아래 network 재시작은 ssh 연결이 끊기므로 ssh 재접속 해야 합니다.)

/etc/init.d/stubby restart
/etc/init.d/dnsmasq restart
/etc/init.d/odhcpd stop
/etc/init.d/odhcpd disable
/etc/init.d/network restart

dnssec 유효성 검사 작동 확인을 위해 dig 명령으로 확인합니다. flags: qr rd ra ad; 부분에서 ad플래그는 dnssec 유효성 검사가 작동 중임을 나타냅니다. 해당 플래그가 없으면 dnssec 유효성 검사가 작동하지 않는 것 입니다.

opkg install bind-dig
dig qquack.org +dnssec +multi @127.0.0.1

; <<>> DiG 9.16.6 <<>> qquack.org +dnssec +multi @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14736
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;qquack.org.            IN A

;; ANSWER SECTION:
qquack.org.             300 IN A 104.24.106.41
qquack.org.             300 IN A 104.24.107.41
qquack.org.             300 IN A 172.67.214.156
qquack.org.             300 IN RRSIG A 13 2 300 (
                                20201101035709 20201030015709 34505 qquack.org.
                                xUSjpHO9vKhOlj3Dbw3IFFxSpwXYyg1Dwf9m8nr6H+kF
                                bB2RaUirMeemaaazEt38g/yuUgYLUlph4Hl72vuBNg== )

;; Query time: 130 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Oct 31 11:57:09 KST 2020
;; MSG SIZE  rcvd: 233

OpenWrt에 https-dns-proxy 사용하기 (DoH)

https-dns-proxy 패키지를 설치하고 설치를 완료하면 자동으로 서비스를 시작하는데 일단 서비스를 종료시킵니다. (필요한 경우 luci-app-https-dns-proxy를 설치하면 luci를 통해 설정을 할 수 있습니다.)

opkg update
opkg install https-dns-proxy ca-bundle
/etc/init.d/https-dns-proxy stop

/etc/config/https-dns-proxy를 다음과 같이 수정합니다. 저는 구글 dns는 주석처리하여 cloudflare dns만을 이용하고, option update_dnsmasq_config 는 '*" 에서 '-'로 수정하여 https-dns-proxy 데몬이 시작시 /etc/config/https-dns-proxy 설정을 스크립트에 의해 자동으로 /etc/config/dhcp화일에 반영하고 dnsmasq 데몬을 재시작하는데 이를 방지하였습니다.

config main 'config'
        option update_dnsmasq_config '-'

#config https-dns-proxy
#       option bootstrap_dns '8.8.8.8,8.8.4.4'
#       option resolver_url 'https://dns.google/dns-query'
#       option listen_addr '127.0.0.1'
#       option listen_port '5053'
#       option user 'nobody'
#       option group 'nogroup'

config https-dns-proxy
        option bootstrap_dns '1.1.1.1,1.0.0.1'
        option resolver_url 'https://cloudflare-dns.com/dns-query'
        option listen_addr '127.0.0.1'
        option listen_port '5054'
        option user 'nobody'
        option group 'nogroup'

/etc/config/network를 다음을 추가 및 편집합니다. 그리고 설정하는 김에 ipv6 대한 설정을 죽입니다. (위의 stubby의 설정과 같음)

...
config interface 'lan'
        ...
        option ipv6 '0'
        option delegate '0'

config interface 'wan'
        ...
        option peerdns '0'
        option dns '127.0.0.1'
        option ipv6 '0'
        option delegate '0'

config interface 'wan6'
        ...
        option peerdns '0'
 #      option dns '0::1'
        option ipv6 '0'
        option delegate '0'
        option auto '0'
...

dnssec 사용을 위해 dnsmasq패키지를 제거하고 dnsmasq-full 패키지를 설치합니다.

opkg install dnsmasq-full --download-only && opkg remove dnsmasq && opkg install dnsmasq-full --cache . && rm *.ipk

/etc/config/dhcp를 다음과 같이 추가 및 편집합니다.

config dnsmasq
        ...
        option noresolv '1'
        option dnssec '1'
        option dnsseccheckunsigned '1'
        list server '127.0.0.1#5054'
        list server '/openwrt.pool.ntp.org/1.1.1.1'

config dhcp 'lan'
        ...
        option dhcpv4 'server'
        option dhcpv6 'disabled'
        list ra_flags 'none'

config dhcp 'wan'
        ...
        option ignore '1'
        list ra_flags 'none'

config dhcp 'wan6'
        ....
        option ignore '1'
        list ra_flags 'none'
...

서비스 재시작 (아래 network 재시작은 ssh 연결이 끊기므로 ssh 재접속 해야 합니다.)

/etc/init.d/https-dns-proxy start
/etc/init.d/dnsmasq restart
/etc/init.d/odhcpd stop
/etc/init.d/odhcpd disable
/etc/init.d/network restart

위의 stubby 처럼 dig 명령으로 dnssec 테스트를 해보시기 바랍니다.

DNS hijacking/redirect

라우터 내부 lan에 물려있는 개별 장치의 dns 설정은 라우터의 dns설정을 우선하기 때문에 lan 내부 장치의 dns 설정 주소가 라우터 주소(192.168.1.1)가 아니거나 자동으로 받기가 아니라면 lan 내부 장치의 dns트래픽은 라우터를 거쳐갈뿐 라우터 dns를 이용하지 않습니다. lan 내부 장치들에게 라우터 dns 이용을 강제하고 싶다면 dns 트래픽을 가로채기(하이재킹)를 구성합니다. vi편집기로 아래와 같이 방화벽 설정화일을 수정합니다. (단 클라이언트가 브라우저나 별도 프로그램으로 DoT, DoH를 수행하도록 설정된 경우 요청을 리디렉션하지 않습니다.)

vi /etc/config/firewall

...
config redirect
        option name 'DNS-hijacking'
        option src 'lan'
        option src_dport '53'
        option proto 'tcp udp'
        option target 'DNAT'

방화벽 재시작

/etc/init.d/firewall restart

참고사이트

5 Comments

  1. ㅇㅇ

    안녕하세요 하나 질문이 있는데요
    -ash: /etc/config/stubby: Permission denied 라고 나오면 권한을 어떻게 주나요?

    • qquack

      어떤 상황에서 permission denied 가 나온건가요?
      stubby는 root가 아닌 사용자 stubby가 데몬을 구동합니다.
      stubby 데몬이 구동 안된것 같은데
      cat /etc/passwd | grep stubby 로 stubby 사용자가 있는지 확인하고 사용자가 있다면
      일단 로그를 확인해서 어떤 상황인지 확인이 필요해 보여요.

  2. ㅇㅇ

    솔직히 저는 이런거 해본적이 없어서 무슨 소리인지 아예 모르겠네요 ㅎㅎ;
    그냥 putty로 ssh에 접속한다음에 id pw치고 /etc/config/stubby 치니까 권한이 없다고 나옵니다

    • qquack

      openwrt는 리눅스 기반의 임베디드 기기(공유기) 운영체제 입니다.
      openwrt 대부분의 설정을 변경하거나 관리하는데 luci라는 웹인터페이스가 있어 편리하게 이용할 수 있으며 luci에서 하는 설정과 cui에서 하는 설정은 동일합니다.
      다만 luci에 없는 기능을 사용하거나 luci가 지원하지 않는 패키지를 사용한다든가 또는 인증서 따위를 만든다던가 하는 작업을 위해서는 cui환경이 필요하며 그러러면 리눅스에 대한 아주 약간의 지식이 있어야 해요.
      파일/디렉토리 구조와 권한, 기본적인 명령어와 편집기 사용법. 요정도만 아셔도 여기에 뭘 써놓은건지 눈에 보이실거고 필요한 설정을 하실 수 있으며, 여기에 없는 다른 특별한 기능 또한 이용할 수 있을거예요.
      화이팅^^

    • qquack

      위 글에서 /etc/config/stubby를 다음과 편집합니다.

      여기서 막히셨군요!!

      *nix 환경에서 편집기는 여러 종류가 있는데 대표적인 것이 vi, nano 같은 편집기가 있습니다.
      편집을 위해서는 vi /etc/config/stubby (vi 화일명) 이런 형식으로 하시면 되는데 vi 처음이시면 힘드실 겁니다.
      지금까지 경험하지 못한 텍스트 편집기로 사용법을 익히셔야해요.
      nano는 아마 패키지 설치 필요할 겁니다. opkg update && opkg install nano

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다