给定两个 DNS 服务器,一个在本地主机(127.0.0.1:53)上运行,另一个在 Docker 容器(172.18.0.3:5300)中运行。
当我尝试检查域名解析时通过 localhost DNS使用dig
或nslookup
命令请求被拒绝:
adam@adam-desktop:~$ nslookup whoami.docker
Server: 127.0.0.1
Address: 127.0.0.1#53
** server can't find whoami.docker: REFUSED
并检查dig
但结果类似:
adam@adam-desktop:~$ dig A whoami.docker
; <<>> DiG 9.18.1-1ubuntu1.3-Ubuntu <<>> A whoami.docker
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 10447
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;whoami.docker. IN A
;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Sun Mar 26 18:59:31 CEST 2023
;; MSG SIZE rcvd: 42
然后创建以下日志条目:
adam@adam-desktop:~$ tail -F /var/log/syslog:
[...]
Mar 26 18:45:27 adam-desktop dnsmasq[10105]: query[A] whoami.docker from 127.0.0.1
Mar 26 18:45:27 adam-desktop dnsmasq[10105]: forwarded whoami.docker to 172.18.0.3
Mar 26 18:45:32 adam-desktop dnsmasq[10105]: query[A] whoami.docker from 127.0.0.1
Mar 26 18:45:32 adam-desktop dnsmasq[10105]: config error is REFUSED
但是当我在命令中指定第二个 DNS 服务器时,响应是预期的:
adam@adam-desktop:~$ dig A @172.18.0.3 -p 5300 whoami.docker
; <<>> DiG 9.18.1-1ubuntu1.3-Ubuntu <<>> A @172.18.0.3 -p 5300 whoami.docker
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5930
;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;whoami.docker. IN A
;; ANSWER SECTION:
whoami.docker. 0 IN A 172.18.0.4
;; Query time: 3 msec
;; SERVER: 172.18.0.3#5300(172.18.0.3) (UDP)
;; WHEN: Sun Mar 26 18:58:08 CEST 2023
;; MSG SIZE rcvd: 58
所以我不明白为什么不使用解析链:
请求(whoami.docker)->DNS1(127.0.0.1:53)->DNS2(172.18.0.3):找到条目(172.18.0.4 - whoami.docker)->并返回给客户端。
本地主机 DNS 配置(dnsmasq配置文件):
port=53
domain-needed
bogus-priv
strict-order
no-resolv
# Private DNS server on Docker network
server=/docker/172.18.0.3
#Use the Google nameservers
server=8.8.8.8
server=1.1.1.1
rebind-domain-ok=/.docker/
user=dnsmasq
#group=dnsmasq
listen-address=172.18.0.1, 172.17.0.1, 127.0.0.1
bind-interfaces
cache-size=0
log-queries
NetworkManager 配置(/etc/NetworkManager/NetworkManager.conf):
[main]
dns=dnsmasq
plugins=ifupdown,keyfile
[...]
第二个 DNS 服务器配置(在 Docker 容器内 - IP 地址:172.18.0.3):
port=5300
domain-needed
bogus-priv
log-queries
no-resolv
no-hosts
strict-order
#Use the Google nameservers
server=8.8.8.8
server=8.8.4.4
#serve all company queries using a specific nameserver
domain=docker
#explicitly define host-ip mappings
# Testing container
address=/whoami.docker/172.18.0.4
内容/etc/resolv.conf:
nameserver 127.0.0.1
search home
options edns0 trust-ad
Docker-Compose 文件定义了DNS和我是谁容器:
version: '3.9'
services:
dnsmasq:
image: jpillora/dnsmasq
container_name: dnsmasq
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./dnsmasq.conf:/etc/dnsmasq.conf:ro
- ./dnsmasq.d:/etc/dnsmasq.d:rw
networks:
devnet:
ipv4_address: 172.18.0.3
logging:
options:
max-size: 100m
ports:
- "0.0.0.0:5300:53/udp"
- "0.0.0.0:5300:53/tcp"
- "0.0.0.0:5380:8080"
environment:
- HTTP_USER=foo
- HTTP_PASS=bar
# - VIRTUAL_HOST=ns.dev.home
whoami:
image: jwilder/whoami
container_name: whoami
restart: always
ports:
- "0.0.0.0:8000:8000"
environment:
- VIRTUAL_HOST=whoami.docker
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
devnet:
ipv4_address: 172.18.0.4
networks:
devnet:
driver: "bridge"
external: true
enable_ipv6: false
答案1
我按照接下来的文章解决了我的问题。
第一步:我使用 NetworkManager 内置的 dnsmasq 而不是独立安装:
DNSMasq + 网络管理器 + Docker = 有趣?
第二步:我修改了 Docker Compose 文件:在端口映射中删除了主机端口定义:
version: '3.9'
services:
dnsmasq:
image: jpillora/dnsmasq
container_name: dnsmasq
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./dnsmasq.conf:/etc/dnsmasq.conf:ro
- ./dnsmasq.d:/etc/dnsmasq.d:rw
networks:
devnet:
ipv4_address: 172.18.0.3
logging:
options:
max-size: 100m
ports:
- "53/udp"
- "53/tcp"
- "0.0.0.0:5380:8080"
environment:
- HTTP_USER=foo
- HTTP_PASS=bar
whoami:
image: jwilder/whoami
container_name: whoami
restart: always
ports:
- "0.0.0.0:8000:8000"
environment:
- VIRTUAL_HOST=whoami.dev.home
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
devnet:
ipv4_address: 172.18.0.4
networks:
devnet:
driver: "bridge"
external: true
enable_ipv6: false
第三步:修改了远程 DNS 服务器(在 Docker 网络上)上的 dnsmasq 配置文件,并将域配置分离为独立配置文件,灵感来自:
在 Docker 中运行 dnsmasq
/etc/dnsmasq.conf:
port=53
domain-needed
bogus-priv
no-hosts
keep-in-foreground
bind-interfaces
no-resolv
expand-hosts
server=8.8.8.8
server=8.8.4.4
# changed domain from .docker to .dev.home
domain=dev.home
#log all dns queries
log-queries
conf-dir=/etc/dnsmasq.d
/etc/dnsmasq/dnsmasq.d/1.whoami.conf:
address=/whoami.dev.home/172.18.0.4
txt-record=txt.whoami.dev.home,txt-whoami.whoami.dev.home
第四步: 为 UFW 添加额外规则(/etc/ufw/after.rules)以允许 Docker 内部网络正常运作,然后如何在不禁用 Iptables 的情况下修复 Docker 和 UFW 安全漏洞