linux更改源地址发送数据包,发往Docker容器内的数据包源地址被修改的研究

引言

此文档是对发往Docker容器内的数据包源地址被修改的研究做的实践记录。

实践环境一

Centos7.2+Docker1.12.6

关闭firewalld:

systemctl stop firewalld

设置selinux为Permissive模式:

setenforce 0

/etc/docker/daemon.json内容:

{

"userland-proxy": true

}

创建名为python的容器:

docker run -itd --name python --network bridge -p 8000:9999/udp --entrypoint bash python:2.7.15

容器内接收udp数据包的程序内容为:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定端口:

s.bind(('0.0.0.0', 9999))

print 'Bind UDP on 9999...'

while 1:

# 接收数据:

data, addr = s.recvfrom(1024)

print 'addr: {0}, data: {1}'.format(addr, data)

路由信息:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation网桥docker0设备信息:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

一、通过另一台主机向当前主机发送数据包

1.192.168.84.75主机上运行接收udp数据包的程序,运行配置基于实践环境,在192.168.84.79主机上通过 echo mac | nc -s 192.168.84.79 -p 42731 -u 192.168.84.75 8000(产生数据包的源地址、源端口与目的地址、目的端口为:192.168.84.79.42731 > 192.168.84.75.8000) 向192.168.84.75发送数据包。

对192.168.84.79主机的网卡进行抓包处理:

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

13:33:15.227775 IP (tos 0x0, ttl 64, id 58746, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.42731 > 192.168.84.75.8000: [bad udp cksum 0x2a09 -> 0x3f53!] UDP, length 4

分别对192.168.84.75主机的lo、物理网卡(eno16777984)、docker0以及容器的网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

13:33:25.690285 IP (tos 0x0, ttl 64, id 58746, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.42731 > 192.168.84.75.8000: [udp sum ok] UDP, length 4

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:33:25.690319 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:33:25.690354 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

13:33:25.690362 IP (tos 0x0, ttl 63, id 58746, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.42731 > 172.17.0.2.9999: [udp sum ok] UDP, length 4

tcpdump -i vethc4d778f -nn -vv

tcpdump: listening on vethc4d778f, link-type EN10MB (Ethernet), capture size 262144 bytes

13:33:25.690332 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:33:25.690354 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

13:33:25.690364 IP (tos 0x0, ttl 63, id 58746, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.42731 > 172.17.0.2.9999: [udp sum ok] UDP, length 4

由上述的时间可知数据包先经过84.79主机的网卡,然后数据包被发往84.75主机,在84.75主机上经过的设备依次为:主机网卡(eno16777984 )---> docker0 ---> 容器网卡(vethc4d778f)

数据包发送前与发送后84.75主机的nat表的对比:

发送前执行 iptables -t nat -nvL > pre

发送后执行 iptables -t nat -nvL > now

然后通过diff命令对比两个文件的内容:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:84.79主机发送的数据包源地址、源端口与目的地址、目的端口分别为:192.168.84.79.42731 > 192.168.84.75.8000。数据包从主机网卡eno16777984流出后,首先经过PREROUTING链,此时匹配到动作DOCKER,DOCKER链的规则是:-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER,即当数据包的地址类型为本地地址LOCAL时,将执行DOCKER链的规则匹配。LOCAL本地地址不仅指127.0.0.1,也包括本机IP。因此数据包(192.168.84.79.42731 > 192.168.84.75.8000)能够匹配到DOCKER。DOCKER链的第一条规则:-A DOCKER -i docker0 -j RETURN,表示流入docker0的设备的数据包将返回到DOCKER链的调用处;第二条规则:-A DOCKER ! -i docker0 -p udp -m udp --dport 8000 -j DNAT --to-destination 172.17.0.2:9999,表示不是流入docker0设备、udp协议、目的端口是8000的数据包将其目的地址修改为172.17.0.2,目的端口修改为9999。数据包满足第二条规则此时数据包的源地址、源端口与目的地址、目的端口变为:192.168.84.79.42731 > 172.17.0.2.9999。数据包经过路由判断目的地址(172.17.0.2)不是发往本机,于是经过FORWARD到达POSTROUTING链,POSTROUTING链的第一条规则:-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE,表示对不是从docker0网卡流出且源地址是172.17网段的数据包进行源地址伪装。数据包不满足这条匹配规则。第二条规则:-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p udp -m udp --dport 9999 -j MASQUERADE,表示对源地址、目的地址均为172.17.0.2/32、udp协议、目的端口为9999的数据包进行源地址伪装,同样数据包也不满足第二条规则。此时数据包的源地址、端口与目的地址、端口没有发生变化依然是:192.168.84.79.42731 > 172.17.0.2.9999。数据包从POSTROUTING链出来后根据路由规则(172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0)会被发往docker0设备,发往docker0设备的数据包源地址、端口与目的地址、端口同样没有发生变化(通过上述对docker0的抓包分析也可知)。docker0设备通过ARP找到ip地址为172.17.0.2的设备vethc4d778f,进而将数据包发往vethc4d778f此设备,vethc4d778f设备接收的数据包的源地址、源端口与目的地址、目的端口依然为:192.168.84.79.42731 > 172.17.0.2.9999。因此程序接收到的数据包的源地址为:192.168.84.79,程序的输出结果也可证实:addr: ('192.168.84.79', 42731), data: mac

在84.79主机上执行 echo mac | nc -s 127.0.0.1 -p 42731 -u 192.168.84.75 8000 ,报错误信息Ncat: Invalid argument.

二、本机上通过网卡ip地址发送数据包

在192.168.84.75主机上执行 echo mac | nc -s 192.168.84.75 -p 34191 -u 192.168.84.75 8000

分别lo、物理网卡(eno16777984)、docker0以及容器的网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:37:07.072740 IP (tos 0x0, ttl 64, id 64295, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.75.34191 > 172.17.0.2.9999: [bad udp cksum 0xc124 -> 0xc1c4!] UDP, length 4

13:37:12.075322 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:37:12.075355 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethc4d778f -nn -vv

tcpdump: listening on vethc4d778f, link-type EN10MB (Ethernet), capture size 262144 bytes

13:37:07.072758 IP (tos 0x0, ttl 64, id 64295, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.75.34191 > 172.17.0.2.9999: [bad udp cksum 0xc124 -> 0xc1c4!] UDP, length 4

13:37:12.075332 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:37:12.075355 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

可知数据包仅经过docker0然后去往容器设备vethc4d778f,并没有经过绑定192.168.84.75 IP的网卡eno16777984

数据包发送前与发送后84.75主机的nat表的对比:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:echo mac | nc -s 192.168.84.75 -p 34191 -u 192.168.84.75 8000发出的数据包源地址、源端口与目的地址、目的端口为:192.168.84.75.34191 > 192.168.84.75.8000。经过实践(实践本地访问的数据包经过的链与设备的次序一文)可知,在本机上通过ip地址访问发出的数据包仅经过OUTPUT与POSTROUTING链。数据包从本地进程发出后,经过OUTPUT链,匹配到DOCKER链的第二条规则,即将数据包的目的地址、目的端口更改为172.17.0.2:9999,因此经过OUTPUT链后的数据包源地址、源端口与目的地址、目的端口变为:192.168.84.75.34191 > 172.17.0.2.9999,紧接着经过POSTROUTING链,数据包仅被POSTROUTING链的默认规则匹配,而没有被更改源地址的两条规则匹配到,因此从POSTROUTING链出来的数据包源地址、源端口与目的地址、目的端口依然为:192.168.84.75.34191 > 172.17.0.2.9999。根据路由规则,数据包会被发往docker0设备,然后被发往容器设备vethc4d778f,最后程序收到的数据包的源ip为192.168.84.75,结果可证实:addr: ('192.168.84.75', 34191), data: mac。

echo mac | nc -s 127.0.0.1 -p 34191 -u 192.168.84.75 8000 Ncat: Invalid argument.

三、本机上通过127.0.0.1地址发送数据包

在192.168.84.75主机上执行 echo mac | nc -s 127.0.0.1 -p 33089 -u 127.0.0.1 8000

分别对主机的lo、物理网卡(eno16777984)、docker0以及容器的网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

13:41:30.463055 IP (tos 0x0, ttl 64, id 54997, offset 0, flags [DF], proto UDP (17), length 32)

127.0.0.1.33089 > 127.0.0.1.8000: [bad udp cksum 0xfe1f -> 0x90e6!] UDP, length 4

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:41:30.463419 IP (tos 0x0, ttl 64, id 35536, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.33987 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x2b72!] UDP, length 4

13:41:35.467315 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:41:35.467348 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethc4d778f -nn -vv

tcpdump: listening on vethc4d778f, link-type EN10MB (Ethernet), capture size 262144 bytes

13:41:30.463430 IP (tos 0x0, ttl 64, id 35536, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.33987 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x2b72!] UDP, length 4

13:41:35.467325 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:41:35.467348 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

可知数据包在主机上经过的设备次序为:lo ---> docker0 ---> vethc4d778f

数据包发送前与发送后主机nat表的对比如下:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:这种访问方式数据包经过的设备与链的次序是:OUTPUT ---> POSTROUTING ---> lo设备 ---> PREROUTING ---> INPUT ---> 用户空间(docker-proxy)---> OUTPUT ---> POSTROUTING。本地监听8000端口的进程是docker-proxy(/usr/bin/docker-proxy -proto udp -host-ip 0.0.0.0 -host-port 8000 -container-ip 172.17.0.2 -container-port 9999),查看如下:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation从lo设备流出的数据包(127.0.0.1.33089 > 127.0.0.1.8000),经过PREROUTING链与INPUT链后被本地8000进程docker-proxy处理,处理后数据包的源地址、源端口与目的地址、目的端口变为: 172.17.0.1.33987 > 172.17.0.2.9999;然后数据包经过docker0后发往容器设备vethc4d778f,最后被容器内的程序接收到,程序的输出为:addr: ('172.17.0.1', 33987), data: mac

echo mac | nc -s 192.168.84.75 -p 33089 -u 127.0.0.1 8000(程序能够收到数据包)

lo设备、docker0与容器网卡抓包结果:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

13:46:14.238701 IP (tos 0x0, ttl 64, id 54998, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.75.33089 > 127.0.0.1.8000: [bad udp cksum 0x9412 -> 0xfaf3!] UDP, length 4

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:46:14.238980 IP (tos 0x0, ttl 64, id 35537, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.36234 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x22ab!] UDP, length 4

13:46:19.243339 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:46:19.243377 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethc4d778f -nn -vv

tcpdump: listening on vethc4d778f, link-type EN10MB (Ethernet), capture size 262144 bytes

13:46:14.238992 IP (tos 0x0, ttl 64, id 35537, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.36234 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x22ab!] UDP, length 4

13:46:19.243350 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:46:19.243377 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序输出结果:addr: ('172.17.0.1', 36234), data: mac

四、通过容器ip地址发送数据包

192.168.84.75主机上容器python的ip地址为172.17.0.2,可通过下面方式获得:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

在主机上执行 echo mac | nc -s 172.17.0.1 -p 42883 -u 172.17.0.2 9999分别对192.168.84.75主机的lo、物理网卡(eno16777984)、docker0以及容器的网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i eno16777984 udp port 9999 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:49:05.123460 IP (tos 0x0, ttl 64, id 35538, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.42883 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x08b2!] UDP, length 4

13:49:10.139337 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:49:10.139376 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethc4d778f -nn -vv

tcpdump: listening on vethc4d778f, link-type EN10MB (Ethernet), capture size 262144 bytes

13:49:05.123479 IP (tos 0x0, ttl 64, id 35538, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.42883 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x08b2!] UDP, length 4

13:49:10.139347 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:49:10.139376 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

数据包经过的设备依次为:docker0 ---> vethc4d778f

数据包发送前与发送后主机nat对比:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析: echo mac | nc -s 172.17.0.1 -p 42883 -u 172.17.0.2 9999 产生的数据包的源地址、源端口与目的地址、目的端口为:172.17.0.1.42883 > 172.17.0.2.9999。实践发现,数据包在用户空间内产生,然后从OUTPUT链流向POSTROUTING链。紧接着数据包经过docker0,经过容器设备vethc4d778f被程序接收,程序的输出结果为:addr: ('172.17.0.1', 42883), data: mac

echo mac | nc -s 172.17.0.2 -p 42883 -u 172.17.0.2 9999

libnsock mksock_bind_addr(): Bind to 172.17.0.2:42883 failed (IOD #1): Cannot assign requested address (99)

docker0与容器网卡抓包结果:

tcpdump -i docker0 -nn -vv(数据包的源地址、源端口已经被修改)

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:51:26.388949 IP (tos 0x0, ttl 64, id 35539, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.54670 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0xdaa6!] UDP, length 4

13:51:31.403315 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:51:31.403347 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethc4d778f -nn -vv

tcpdump: listening on vethc4d778f, link-type EN10MB (Ethernet), capture size 262144 bytes

13:51:26.388966 IP (tos 0x0, ttl 64, id 35539, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.54670 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0xdaa6!] UDP, length 4

13:51:31.403325 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:51:31.403347 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序结果:addr: ('172.17.0.1', 54670), data: mac

echo mac | nc -s 127.0.0.1 -p 42883 -u 172.17.0.2 9999 Ncat: Invalid argument.

实践环境二

Centos7.2 + Docker1.12.6

关闭firewalld:

systemctl stop firewalld

设置selinux为Permissive模式:

setenforce 0

/etc/docker/daemon.json内容:

{

"userland-proxy": false

}

创建名为python的容器:

docker run -itd --name python --network bridge -p 8000:9999/udp --entrypoint bash python:2.7.15

容器内接收udp数据包的程序内容为:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定端口:

s.bind(('0.0.0.0', 9999))

print 'Bind UDP on 9999...'

while 1:

# 接收数据:

data, addr = s.recvfrom(1024)

print 'addr: {0}, data: {1}'.format(addr, data)

路由信息:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

网桥docker0设备信息:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation对dockerd进程添加 userland-proxy=false 的配置后,基于上述命令创建完容器与之前对比存在以下三点不同:

docker-proxy进程消失

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

dockerd进程监听8000端口

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

nat表的POSTROUTING链多了一条源地址伪装的规则

-A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE

(将源地址类型为LOCAL且从docker0设备流出的数据包的源地址伪装成docker0设备的地址)

一、通过另一台主机向当前主机发送数据包

192.168.84.75主机上运行接收udp数据包的程序,运行配置基于实践环境,在192.168.84.79主机上通过 echo mac | nc -s 192.168.84.79 -p 55902 -u 192.168.84.75 8000 发送数据包。

对192.168.84.79主机的网卡进行抓包处理:

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

13:57:35.975290 IP (tos 0x0, ttl 64, id 58747, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.55902 > 192.168.84.75.8000: [bad udp cksum 0x2a09 -> 0x0be0!] UDP, length 4

分别对192.168.84.75主机的lo、物理网卡(eno16777984)、docker0以及容器的网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

13:57:46.437799 IP (tos 0x0, ttl 64, id 58747, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.55902 > 192.168.84.75.8000: [udp sum ok] UDP, length 4

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

13:57:46.437850 IP (tos 0x0, ttl 63, id 58747, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.55902 > 172.17.0.2.9999: [udp sum ok] UDP, length 4

13:57:51.451317 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:57:51.451355 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

13:57:46.437863 IP (tos 0x0, ttl 63, id 58747, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.79.55902 > 172.17.0.2.9999: [udp sum ok] UDP, length 4

13:57:51.451327 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

13:57:51.451355 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

数据包流经设备的顺序依次为:eno16777984(84.79) ---> eno16777984(84.75) ---> docker0 ---> vethcbcc4e9

数据包发送前与发送后主机nat表对比:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:84.75主机eno16777984网卡接收的数据包的源地址、源端口与目的地址、目的端口为:192.168.84.79.55902 > 192.168.84.75.8000,此时数据包经过PREROUTING链被DOCKER链的-A DOCKER -p udp -m udp --dport 8000 -j DNAT --to-destination 172.17.0.2:9999规则匹配,数据包的源地址、源端口与目的地址、目的端口变为:192.168.84.79.55902 > 172.17.0.2.9999,紧接着数据包经过路由判断,判断其不是发往本机的包,则通过FORWARD到达POSTROUTING链。POSTROUTING链此时有3条规则,第一条规则-A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE,表示将源地址类型为LOCAL且从docker0设备流出的数据包的源地址修改为docker0设备的地址,这一条不满足条件;第二条规则-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE,表示对源地址为172.17网段且不是从docker0设备流出的包进行源地址伪装,这一条不满足条件。第三条规则-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p udp -m udp --dport 9999 -j MASQUERADE,表示对源地址与目的地址均为172.17.0.2且目的端口为udp协议的9999的数据包进行源地址伪装,第三条同样不满足条件。POSTROUTING链出来的数据包源地址、源端口与目的地址、目的端口为:192.168.84.79.55902 > 172.17.0.2.9999,接着数据包被发往docker0,然后发往容器设备vethcbcc4e9,最后被程序接收,程序的输出结果为:addr: addr: ('192.168.84.79', 55902), data: mac

192.168.84.79主机上执行 echo mac | nc -s 127.0.0.1 -p 55902 -u 192.168.84.75 8000 Ncat: Invalid argument.

二、本机上通过网卡ip地址发送数据包

在192.168.84.75主机上执行 echo mac | nc -s 192.168.84.75 -p 41003 -u 192.168.84.75 8000

分别lo设备、物理网卡(eno16777984)、docker0以及容器网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:03:41.089945 IP (tos 0x0, ttl 64, id 64296, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.41003 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x100a!] UDP, length 4

14:03:46.091328 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:03:46.091387 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:03:41.089961 IP (tos 0x0, ttl 64, id 64296, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.41003 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x100a!] UDP, length 4

14:03:46.091343 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:03:46.091387 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

可知,数据包仅经过docker0与容器设备vethcbcc4e9

数据包发送前与发送后主机nat表对比:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:echo mac | nc -s 192.168.84.75 -p 41003 -u 192.168.84.75 8000 发出的数据包的源地址、源端口与目的地址、目的端口为:192.168.84.75.41003 > 192.168.84.75.8000,内核将数据包发送给本地进程dockerd处理,dockerd只负责接收而并没有做任何的处理,此时数据包经过OUTPUT链被DOCKER链的规则 -A DOCKER -p udp -m udp --dport 8000 -j DNAT --to-destination 172.17.0.2:9999(将udp协议、目的端口为8000的数据包的目的地址与端口修改为172.17.0.2.9999)匹配,此时数据包的源地址、源端口与目的地址、目的端口变为:192.168.84.75.41003 > 172.17.0.2.9999。紧接着数据包经过POSTROUTING链,被规则 -A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE匹配,这条规则表示从docker0设备流出且源地址类型为LOCAL的数据包将其源地址修改为docker0的地址(这里是172.17.0.1),为什么数据包(192.168.84.75.41003 > 172.17.0.2.9999)能够匹配到这条规则呢,不妨分析一下,首先数据包的源地址为192.168.84.75符合 -m addrtype --src-type LOCAL定义;为什么数据包能够满足 -o docker0的定义呢,数据包分明还没有经过docker0设备,此处为何就匹配到了从docker0设备流出的规则呢?按照自身理解,数据包将会流入docker0设备,当然也会从docker0设备流出,但流入docker0设备在前从docker0设备流出在后,因此这里想要将-A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE规则换成-A POSTROUTING -i docker0 -m addrtype --src-type LOCAL -j MASQUERADE,结果报出错误“iptables v1.4.21: Can't use -i with POSTROUTING”,即POSTROUTING链只能通过 -o 指定数据包流出的设备,只要数据包经过的下一个设备会是docker0且会从docker0流出则此处会匹配到这条规则,此时数据包的源地址、源端口与目的地址、目的端口变为:172.17.0.1.41003 > 172.17.0.2.9999。接着数据包经过docker0设备发往容器设备vethcbcc4e9,进而被程序接收,程序的输出结果为:addr: ('172.17.0.1', 41003), data: mac

echo mac | nc -s 127.0.0.1 -p 41003 -u 192.168.84.75 8000

docker0与容器网卡抓包结果:

tcpdump -i docker0 -nn -vv(数据包的源地址已经被修改)

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:06:19.694983 IP (tos 0x0, ttl 64, id 64297, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.41003 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x100a!] UDP, length 4

14:06:24.699338 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:06:24.699375 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:06:19.695000 IP (tos 0x0, ttl 64, id 64297, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.41003 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x100a!] UDP, length 4

14:06:24.699348 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:06:24.699375 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序结果:addr: ('172.17.0.1', 41003), data: mac

三、本机上通过127.0.0.1发送数据包

在192.168.84.75主机上执行 echo mac | nc -s 127.0.0.1 -p 44818 -u 127.0.0.1 8000

分别主机的lo设备、物理网卡(eno16777984)、docker0以及容器网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

tcpdump -i eno16777984 udp port 8000 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:08:58.946048 IP (tos 0x0, ttl 64, id 54997, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.44818 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x0123!] UDP, length 4

14:09:03.947336 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:09:03.947379 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:08:58.946065 IP (tos 0x0, ttl 64, id 54997, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.44818 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x0123!] UDP, length 4

14:09:03.947349 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:09:03.947379 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

数据包经过的设备依次为:docker0 ---> vethcbcc4e9

数据包发送前与发送后nat表规则对比:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:echo mac | nc -s 127.0.0.1 -p 44818 -u 127.0.0.1 8000 产生的数据包的源地址、源端口与目的地址、目的端口为:127.0.0.1.44818 > 127.0.0.1.8000。这种方式数据包仅经过OUTPUT与POSTROUTING链,当数据包经过OUTPUT链时被DOCKER链的-A DOCKER -p udp -m udp --dport 8000 -j DNAT --to-destination 172.17.0.2:9999规则匹配,此时数据包的源地址、源端口与目的地址、目的端口变为:127.0.0.1.44818 > 172.17.0.2.9999。紧接着数据包在经过POSTROUTING链时被-A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE规则匹配,此时数据包的源地址、端口与目的地址、端口变为:172.17.0.1.44818 > 172.17.0.2.9999。数据包被发往docker0,然后发往容器设备vethcbcc4e9,最后被程序接收,程序的输出结果为:addr: ('172.17.0.1', 44818), data: mac

四、通过容器ip地址发送数据包

192.168.84.75主机上容器python的ip地址为172.17.0.2,可通过下面方式获得:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

在主机上执行 echo mac | nc -s 172.17.0.1 -p 54877 -u 172.17.0.2 9999,分别对主机的lo、物理网卡(eno16777984)、docker0以及容器网卡进行抓包处理:

tcpdump -i lo -nn -vv

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i eno16777984 udp port 9999 -nn -vv

tcpdump: listening on eno16777984, link-type EN10MB (Ethernet), capture size 262144 bytes

无内容

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:10:58.373599 IP (tos 0x0, ttl 64, id 35536, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.54877 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0xd9d7!] UDP, length 4

14:11:03.387315 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:11:03.387349 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:10:58.373617 IP (tos 0x0, ttl 64, id 35536, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.54877 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0xd9d7!] UDP, length 4

14:11:03.387325 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:11:03.387349 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

数据包经过的设备依次为:docker0 ---> vethcbcc4e9

数据包发送前与发送后主机nat对比:

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation分析:echo mac | nc -s 172.17.0.1 -p 54877 -u 172.17.0.2 9999 产生的数据包的源地址、源端口与目的地址、目的端口为:172.17.0.1.54877 > 172.17.0.2.9999。实践发现,数据包从用户空间发出仅经过OUTPUT链与POSTROUTING链。数据包从OUTPUT链流向POSTROUTING链时,被-A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE规则匹配,将源地址类型为LOCAL、从docker0设备流出的数据包的源地址伪装成docker0设备的地址172.17.0.1,此时数据包的源地址、源端口与目的地址、目的端口变为:172.17.0.1.54877 > 172.17.0.2.9999。紧接着数据包经过docker0,经过容器设备vethcbcc4e9被程序接收,程序的输出结果为:addr: ('172.17.0.1', 54877), data: mac

echo mac | nc -s 172.17.0.2 -p 54877 -u 172.17.0.2 9999

libnsock mksock_bind_addr(): Bind to 172.17.0.2:54877 failed (IOD #1): Cannot assign requested address (99)

docker0与容器网卡抓包结果:

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:13:04.045159 IP (tos 0x0, ttl 64, id 35537, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.35950 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x23c7!] UDP, length 4

14:13:09.051330 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:13:09.051367 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:13:04.045176 IP (tos 0x0, ttl 64, id 35537, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.35950 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0x23c7!] UDP, length 4

14:13:09.051340 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:13:09.051367 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序结果:addr: ('172.17.0.1', 35950), data: mac

echo mac | nc -s 127.0.0.1 -p 54877 -u 172.17.0.2 9999

docker0与容器网卡抓包结果:

tcpdump -i docker0 -nn -vv(数据包的源地址被规则 -A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE 修改为docker0地址172.17.0.1)

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:15:08.717851 IP (tos 0x0, ttl 64, id 35538, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.54877 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0xd9d7!] UDP, length 4

14:15:13.723315 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:15:13.723350 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:15:08.717868 IP (tos 0x0, ttl 64, id 35538, offset 0, flags [DF], proto UDP (17), length 32)

172.17.0.1.54877 > 172.17.0.2.9999: [bad udp cksum 0x5843 -> 0xd9d7!] UDP, length 4

14:15:13.723326 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:15:13.723350 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序结果:addr: ('172.17.0.1', 54877), data: mac

去除POSTROUTING链的规则 -A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

执行 echo mac | nc -s 127.0.0.1 -p 54877 -u 172.17.0.2 9999

docker0与容器网卡抓包结果:

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:17:35.597021 IP (tos 0x0, ttl 64, id 35539, offset 0, flags [DF], proto UDP (17), length 32)

127.0.0.1.54877 > 172.17.0.2.9999: [bad udp cksum 0x2b32 -> 0x06e9!] UDP, length 4

14:17:40.603314 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:17:40.603346 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:17:35.597050 IP (tos 0x0, ttl 64, id 35539, offset 0, flags [DF], proto UDP (17), length 32)

127.0.0.1.54877 > 172.17.0.2.9999: [bad udp cksum 0x2b32 -> 0x06e9!] UDP, length 4

14:17:40.603323 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:17:40.603346 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序结果:空,即程序没有接收到数据包

添加将udp协议、源地址类型为LOCAL的数据包的源地址修改为主机地址192.168.84.75

086db83663c5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

执行 echo mac | nc -s 127.0.0.1 -p 54877 -u 172.17.0.2 9999

docker0与容器网卡veth1a4e47a抓包结果:

tcpdump -i docker0 -nn -vv

tcpdump: listening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes

14:20:10.098644 IP (tos 0x0, ttl 64, id 35540, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.75.54877 > 172.17.0.2.9999: [bad udp cksum 0xc124 -> 0x70f6!] UDP, length 4

14:20:15.115338 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:20:15.115377 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

tcpdump -i vethcbcc4e9 -nn -vv

tcpdump: listening on vethcbcc4e9, link-type EN10MB (Ethernet), capture size 262144 bytes

14:20:10.098661 IP (tos 0x0, ttl 64, id 35540, offset 0, flags [DF], proto UDP (17), length 32)

192.168.84.75.54877 > 172.17.0.2.9999: [bad udp cksum 0xc124 -> 0x70f6!] UDP, length 4

14:20:15.115350 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.17.0.2 tell 172.17.0.1, length 28

14:20:15.115377 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.17.0.2 is-at 02:42:ac:11:00:02, length 28

程序结果:addr: ('192.168.84.75', 54877), data: mac

总结

Centos7中更改数据包源地址的操作即SNAT可以在INPUT链与POSTROUTING链两个地方操作。Docker在INPUT链中没有定义SNAT规则,全部的SNAT操作均定义在POSTROUTING链中。所以对Docker数据包的SNAT的研究只需关注POSTROUTING链即可。我们自己产品对docker的使用属于上述实验一的范围,即是将userland设置为true,包括以下几种情况:

如果机器的iptables规则没有做额外的配置,通过外主机向本机访问或在本机上通过ip地址访问,数据包的源地址不会被修改

本机上通过127.0.0.1访问的数据包的源地址会被docker-proxy进程修改,因此本机访问若想要数据包的源地址不被修改,需使用本机ip地址访问

通过上面实践可发现,源地址为127.0.0.1的数据包在多数场景下不能成功发送出去,能够发送出去且能被容器内程序接收到的数据包在容器网卡或docker0那一层其源地址127.0.0.1已经被修改了;即容器内程序接收到的数据包的源地址不可能是127.0.0.1。源地址为127.0.0.1的数据包在传输过程中意义不大,因为无法根据源地址127.0.0.1找到发包的设备

数据包在主机与主机或主机与容器之间传输时,数据包的源地址多数情况下会发生改变,如果某功能是以数据包源IP地址作为来源主机的判断是不可靠的;因为可能取的数据包是处于中间状态的包,这类包的源IP地址可能已被修改,这样就会导致来源主机判断的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值