解密 docker 容器内 DNS 解析原理

这篇具有很好参考价值的文章主要介绍了解密 docker 容器内 DNS 解析原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

这几天在使用 docker 中,碰到了在容器中 DNS 解析的一些问题。故花些时间弄清了原理,写此文章分享。

1. docker run 命令启动的容器

以启动一个 busybox 容器为例:

root@ubuntu20:~# docker run -itd --name u1 busybox
63b59ca8aeac18a09b63aaf4a14dc80895d6de293017d01786cac98cccda62ae
root@ubuntu20:~# docker exec -it u1 sh
/ # 
/ # ping www.baidu.com
PING www.baidu.com (14.119.104.189): 56 data bytes
64 bytes from 14.119.104.189: seq=0 ttl=127 time=34.976 ms
64 bytes from 14.119.104.189: seq=1 ttl=127 time=35.369 ms
^C
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 34.976/35.172/35.369 ms

在容器里可以 ping 通外部的域名。

过程

查看容器中的 /etc/resolv.conf 文件内容:

/ # cat /etc/resolv.conf 
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 192.168.30.2
search localdomain

使用的 DNS 服务器 ip 是 192.168.30.2。

这正是宿主机【我使用的是 Ubuntu 20.04 虚拟机】使用的 DNS 服务器ip地址。在宿主机上使用 systemd-resolve --status 命令可以看到:

root@ubuntu20:~# systemd-resolve --status
....

Link 2 (ens33)
      Current Scopes: DNS         
DefaultRoute setting: yes         
       LLMNR setting: yes         
MulticastDNS setting: no          
  DNSOverTLS setting: no          
      DNSSEC setting: no          
    DNSSEC supported: no          
  Current DNS Server: 192.168.30.2
         DNS Servers: 192.168.30.2
          DNS Domain: localdomain 
          
...

结论

以这种方式启动的容器,容器内部的 /etc/resolv.conf 文件中配置的 ip 是宿主机使用的 DNS 服务器ip。

参考文章:How does the Docker DNS work?

2. docker compose 启动的容器

在使用 docker compose 时,我们知道,一个容器可以使用另一个容器的服务名来获取它的ip地址。

看个例子,docker-compose.yml 文件内容如下:

version: '2'

services:
  redis:
    image: redis:3.2

  busybox:
    image: busybox
    stdin_open: true
    tty: true

它定义了两个服务 redis 和 busybox。

进入 busybox 容器内,可以使用 “redis”来获取 redis 容器的 ip 地址:

root@ubuntu20:~/test# docker-compose up -d
Creating network "test_default" with the default driver
Creating test_redis_1   ... done
Creating test_busybox_1 ... done
root@ubuntu20:~/test# docker-compose ps

     Name                   Command               State    Ports  
------------------------------------------------------------------
test_busybox_1   sh                               Up              
test_redis_1     docker-entrypoint.sh redis ...   Up      6379/tcp

root@ubuntu20:~/test# docker exec -it test_busybox_1 sh
/ # 
/ # ping redis -c 1
PING redis (192.168.112.2): 56 data bytes
64 bytes from 192.168.112.2: seq=0 ttl=64 time=1.103 ms

--- redis ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.103/1.103/1.103 ms

反之亦然。这是怎么做到的呢?

过程

先看看容器中的 /etc/resolv.conf 文件:

/ # cat /etc/resolv.conf 
search localdomain
nameserver 127.0.0.11
options edns0 trust-ad ndots:0

它使用的 DNS 服务器 ip 地址居然是个环回地址 127.0.0.11 !那是怎么做到可以解析域名的呢?

在容器内的环回口抓下包看下:

root@ubuntu20:~/test# docker inspect test_busybox_1 | grep Pid
            "Pid": 211432,
            "PidMode": "",
            "PidsLimit": null,
root@ubuntu20:~/test# nsenter -t 211432 -n tcpdump -i lo -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:11:39.223669 IP 127.0.0.1.58808 > 127.0.0.11.59712: UDP, length 34
10:11:39.223707 IP 127.0.0.1.58808 > 127.0.0.11.59712: UDP, length 34
10:11:39.224305 IP 127.0.0.11.53 > 127.0.0.1.58808: 6751 0/0/0 (23)
10:11:39.224682 IP 127.0.0.11.53 > 127.0.0.1.58808: 18524 1/0/0 A 192.168.112.2 (44)

这里有个小技巧:因为 busybox 容器中并没有 tcpdump 程序,所以使用 nsenter 进入了容器的网络命名空间,执行抓包程序。

通过抓包可以看到:DNS 请求被发给了 127.0.0.11.59712 ?说明有某个服务监听这个 ip地址+端口。
使用 ss 命令查看下:

root@ubuntu20:~/test# nsenter -t 211432 -n ss -unlp
State              Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port             Process             
UNCONN             0                  0                                  127.0.0.11:59712                                0.0.0.0:*                 users:(("dockerd",pid=1078,fd=78))

发现监听这个 ip 地址加端口的居然是 dockerd 程序!原来 DNS 请求是发送给了 dockerd 程序处理了!

但是 DNS 请求目的端口不是 53 吗?怎么变成了这个 59712,这是怎么回事?看下 iptables nat 表:

root@ubuntu20:~/test# nsenter -t 211432 -n iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER_OUTPUT
-N DOCKER_POSTROUTING
-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:43107
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:59712
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 43107 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 59712 -j SNAT --to-source :53

原来有一条 DNAT 规则,将目的 ip 为127.0.0.11,端口为 53 的 udp 数据包,目的端口修改为 59712。一切真相大白!

结论

以 docker compose 启动的容器,使用的 DNS 服务器是 dockerd 程序内部的 DNS 服务器。

它是通过以下三步来实现的:文章来源地址https://www.toymoban.com/news/detail-744757.html

  1. dockerd 在容器的网络命名空间中创建一个监听 127.0.0.11 的 udp socket
  2. 设置容器内 /etc/resolv.conf 文件ip 为 127.0.0.11
  3. 容器内添加 iptable DNAT 规则

到了这里,关于解密 docker 容器内 DNS 解析原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Docker 容器的DNS

    1.简介 DNS服务是域名系统的缩写, 英文全称:Domain Name System,将域名和IP地址相互映射。在容器环境中,DNS至关重要, Docker link Docker link是一个遗留的特性,在新版本的Docker中,一般不推荐使用。简单来说Docker link就是把两个容器连接起来,容器可以使用容器名进行通信,而

    2024年02月01日
    浏览(88)
  • 万字长文深入理解Docker镜像分层原理、容器数据卷、网络通信架构(Docker系列第2章,共3章)

    在执行docker pull时,会发现多个Pull complete 字样,就能体现分层,如果是一个文件,只会有一个Pull complete 。 概念:文件系统是计算机系统中用于组织和管理数据存储的一种方式。它定义了数据如何存储、命名、访问和修改的方式。 举例:如Windows自带的NTFS、FAT32、EXFAT,和L

    2024年04月14日
    浏览(39)
  • 详解【计算机类&面试真题】军队文职考试——第4期(真题+解析):网络时延的组成部分和产生,使用Python来计算传输时延和传播时延 | TIP/IP网络协议的核心是什么?| DNS域名系统的工作原理

      决定放弃了的事,就请放弃得干干净净,那些决定再也不见面的人,就真的不要再见面了。     🎯作者主页: 追光者♂🔥          🌸个人简介:   💖[1] 计算机专业硕士研究生💖   🌟[2] 2022年度博客之星人工智能领域TOP4🌟   🏅[3] 阿里云社区特邀专家博主🏅  

    2024年02月09日
    浏览(68)
  • 【博客629】Linux DNS解析原理与配置

    作用: 程序客户端、下游的 DNS 服务器每次查询 DNS 成功之后,通常会将该 DNS 记录缓存一段时间,避免频繁发出查询请求的耗时。 Linux下的DNS缓存: Linux 系统默认不会在本地建立 DNS 缓存,可以安装 nscd、dnsmasq 等工具提供 DNS 缓存。 2-1、本地hosts 修改本地hosts文件,利用ho

    2024年02月16日
    浏览(37)
  • 容器化背后的魔法之Docker底层逻辑解密

    Docker内部工作原理是怎样的? 现在我们知道了Docker是什么以及它提供了哪些好处,让我们逐个重要的细节来了解。 什么是容器?它们是如何工作的? 在深入研究Docker的内部机制之前,我们首先要了解容器的概念。简单地说,容器是一个隔离和轻量级的运行时环境,封装了一

    2024年02月16日
    浏览(48)
  • 第七次作业 运维高级 docker容器进级版

    1、使用mysql:5.6和 owncloud 镜像,构建一个个人网盘。 (1)拉取相应镜像 (2)运行mysql:5.6容器 (3)运行owncloud容器 (4)查看并验证 之后在浏览器中输入ipaddress:8080 2、安装搭建私有仓库 Harbor (1)下载好harbor和docker-compose (2)上传到Linux服务器 (3)复制docker-compose并修改权限 (4)解压harbor (

    2024年02月12日
    浏览(57)
  • 常见DNS服务网络故障案例解析

    在上网冲浪时,我们经常会遇到网络连接正常,但无法浏览网页的问题。对于这类网络故障,很多时候都与系统的DNS服务有关。为了解决由DNS服务引起的网络故障,本文总结了一些这方面的故障解决案例,希望对大家有所帮助。 故障一、无法清空DNS 缓存 现象:近日,笔者上

    2024年02月06日
    浏览(44)
  • LINUX网络第三章:DNS解析

    首先,我们要知道DNS是什么,DNS(Domain Name System)是域名系统的英文系统,是一种组织成域层次结构和计算机和网络服务命名系统,用于TCP/IP网络。、 DNS实际上是域名解析协议,将域名转化为IP地址 在早期的域名解析的时候,是iana组织负责将域名和IP地址进行对应,并对其进

    2024年01月17日
    浏览(46)
  • 网络安全 Day31-运维安全项目-容器架构下

    通过上个案例(手动创建镜像)发现很麻烦所以用dockerfile自动化创建镜像 这里我们就可以使用Dockerfile文件方法把定义镜像的流程,根据Dockerfile指令指定,最终生成我们想要的自定义 镜像 。 目标: 1️⃣会使用Dockerfile 2️⃣掌握如何书写Dockerfile 任务要求:通过Dockerfile一键

    2024年02月13日
    浏览(41)
  • 华为交换机配置NQA DNS检测IP网络DNS解析速度

      华为HCIA视频教程:超级实用,华为VRP系统文件详解 华为HCIA视频教程:不会传输层协议,HCIA都考不过 华为HCIA视频教程:网络工程师的基本功:网络地址转换NAT 华为HCIP视频教程:DHCP协议原理与配置   组网需求 如图1所示,设备DeviceA通过网络可以连接DNS服务器和主机HostA。

    2024年01月16日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包