Simulate TCP Errors

在 Docker 容器内模拟网络异常#

运行 iptables#

在容器中也可以使用 iptables ,需要在容器中安装它。

运行时可能会报错:

iptables -L
ERROR: problem running iptables: iptables v1.6.1: can't initialize iptables table `filter': Permission denied (you must be root) Perhaps iptables or your kernel needs to be upgraded.

使用 –privileged 启动容器可以解决这个问题。

网上也有说使用 NET_ADMIN 也可以解决问题,不过我没有测试过,使用 NET_ADMIN 的方式如下:

docker run --cap-add NET_ADMIN your_image your_cmd

端口映射#

使用端口映射可以将容器的端口映射到主机上。

如果是桥接的网络模式下,当客户端访问主机的端口时,会先与主机端口建立连接,网络驱动再与容器建立连接。

假设在容器内设置了 iptables 规则拒绝连接,在访问映射出来的主机端口时,连接还是能够正常建立,但是最终请求会失败。

例如,通过下面的语句拒绝对8000端口的连接请求:

iptables -A INPUT -p tcp --dport 8000 -j REJECT  --reject-with tcp-reset

此时如果在容器内对端口进行访问,通过tcpdump抓包可以观察到:

tcpdump -nn -i lo tcp port 8000

09:08:24.126007 IP 127.0.0.1.58712 > 127.0.0.1.8000: Flags [S], seq 1762607628, win 65495, options [mss 65495,sackOK,TS val 1024009329 ecr 0,nop,wscale 7], length 0
09:08:24.126016 IP 127.0.0.1.8000 > 127.0.0.1.58712: Flags [R.], seq 0, ack 1762607629, win 0, length 0

在收到 SYN 包后,服务器立即返回了 RST 包拒绝连接。

但如果在主机上通过 url -v http://localhost:8000 访问时,抓包内容如下:

sudo tcpdump -vv -X -nn -i lo0 tcp port 8000
tcpdump: listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
17:40:32.251192 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64, bad cksum 0 (->3cb6)!)
    127.0.0.1.51172 > 127.0.0.1.8000: Flags [S], cksum 0xfe34 (incorrect -> 0x82b3), seq 2674595427, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 4164216569 ecr 0,sackOK,eol], length 0
        0x0000:  4500 0040 0000 4000 4006 0000 7f00 0001  E..@..@.@.......
        0x0010:  7f00 0001 c7e4 1f40 9f6b 1663 0000 0000  .......@.k.c....
        0x0020:  b002 ffff fe34 0000 0204 3fd8 0103 0306  .....4....?.....
        0x0030:  0101 080a f834 e6f9 0000 0000 0402 0000  .....4..........
17:40:32.251301 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64, bad cksum 0 (->3cb6)!)
    127.0.0.1.8000 > 127.0.0.1.51172: Flags [S.], cksum 0xfe34 (incorrect -> 0x120c), seq 1712797697, ack 2674595428, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 2737450835 ecr 4164216569,sackOK,eol], length 0
        0x0000:  4500 0040 0000 4000 4006 0000 7f00 0001  E..@..@.@.......
        0x0010:  7f00 0001 1f40 c7e4 6617 3801 9f6b 1664  .....@..f.8..k.d
        0x0020:  b012 ffff fe34 0000 0204 3fd8 0103 0306  .....4....?.....
        0x0030:  0101 080a a32a 2f53 f834 e6f9 0402 0000  .....*/S.4......
17:40:32.251314 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.51172 > 127.0.0.1.8000: Flags [.], cksum 0xfe28 (incorrect -> 0x7315), seq 1, ack 1, win 6379, options [nop,nop,TS val 4164216569 ecr 2737450835], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 c7e4 1f40 9f6b 1664 6617 3802  .......@.k.df.8.
        0x0020:  8010 18eb fe28 0000 0101 080a f834 e6f9  .....(.......4..
        0x0030:  a32a 2f53                                .*/S
17:40:32.251324 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.8000 > 127.0.0.1.51172: Flags [.], cksum 0xfe28 (incorrect -> 0x7315), seq 1, ack 1, win 6379, options [nop,nop,TS val 2737450835 ecr 4164216569], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 1f40 c7e4 6617 3802 9f6b 1664  .....@..f.8..k.d
        0x0020:  8010 18eb fe28 0000 0101 080a a32a 2f53  .....(.......*/S
        0x0030:  f834 e6f9                                .4..
17:40:32.251377 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 130, bad cksum 0 (->3c74)!)
    127.0.0.1.51172 > 127.0.0.1.8000: Flags [P.], cksum 0xfe76 (incorrect -> 0xd26d), seq 1:79, ack 1, win 6379, options [nop,nop,TS val 4164216569 ecr 2737450835], length 78
        0x0000:  4500 0082 0000 4000 4006 0000 7f00 0001  E.....@.@.......
        0x0010:  7f00 0001 c7e4 1f40 9f6b 1664 6617 3802  .......@.k.df.8.
        0x0020:  8018 18eb fe76 0000 0101 080a f834 e6f9  .....v.......4..
        0x0030:  a32a 2f53 4745 5420 2f20 4854 5450 2f31  .*/SGET./.HTTP/1
        0x0040:  2e31 0d0a 486f 7374 3a20 6c6f 6361 6c68  .1..Host:.localh
        0x0050:  6f73 743a 3830 3030 0d0a 5573 6572 2d41  ost:8000..User-A
        0x0060:  6765 6e74 3a20 6375 726c 2f37 2e38 372e  gent:.curl/7.87.
        0x0070:  300d 0a41 6363 6570 743a 202a 2f2a 0d0a  0..Accept:.*/*..
        0x0080:  0d0a                                     ..
17:40:32.251407 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.8000 > 127.0.0.1.51172: Flags [.], cksum 0xfe28 (incorrect -> 0x72c8), seq 1, ack 79, win 6378, options [nop,nop,TS val 2737450835 ecr 4164216569], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 1f40 c7e4 6617 3802 9f6b 16b2  .....@..f.8..k..
        0x0020:  8010 18ea fe28 0000 0101 080a a32a 2f53  .....(.......*/S
        0x0030:  f834 e6f9                                .4..
17:40:32.252953 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.8000 > 127.0.0.1.51172: Flags [F.], cksum 0xfe28 (incorrect -> 0x72c5), seq 1, ack 79, win 6378, options [nop,nop,TS val 2737450837 ecr 4164216569], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 1f40 c7e4 6617 3802 9f6b 16b2  .....@..f.8..k..
        0x0020:  8011 18ea fe28 0000 0101 080a a32a 2f55  .....(.......*/U
        0x0030:  f834 e6f9                                .4..
17:40:32.252993 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.51172 > 127.0.0.1.8000: Flags [.], cksum 0xfe28 (incorrect -> 0x72c2), seq 79, ack 2, win 6379, options [nop,nop,TS val 4164216571 ecr 2737450837], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 c7e4 1f40 9f6b 16b2 6617 3803  .......@.k..f.8.
        0x0020:  8010 18eb fe28 0000 0101 080a f834 e6fb  .....(.......4..
        0x0030:  a32a 2f55                                .*/U
17:40:32.253434 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.51172 > 127.0.0.1.8000: Flags [F.], cksum 0xfe28 (incorrect -> 0x72c1), seq 79, ack 2, win 6379, options [nop,nop,TS val 4164216571 ecr 2737450837], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 c7e4 1f40 9f6b 16b2 6617 3803  .......@.k..f.8.
        0x0020:  8011 18eb fe28 0000 0101 080a f834 e6fb  .....(.......4..
        0x0030:  a32a 2f55                                .*/U
17:40:32.253464 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->3cc2)!)
    127.0.0.1.8000 > 127.0.0.1.51172: Flags [.], cksum 0xfe28 (incorrect -> 0x72c2), seq 2, ack 80, win 6378, options [nop,nop,TS val 2737450837 ecr 4164216571], length 0
        0x0000:  4500 0034 0000 4000 4006 0000 7f00 0001  E..4..@.@.......
        0x0010:  7f00 0001 1f40 c7e4 6617 3803 9f6b 16b3  .....@..f.8..k..
        0x0020:  8010 18ea fe28 0000 0101 080a a32a 2f55  .....(.......*/U
        0x0030:  f834 e6fb                                .4..

可以看到连接不但正常建立,而且 curl 还发送了 GET / 的 http 请求,随后没有任何服务器返回,连接就正常关闭了。这就是主机端口映射所产生的效果。

用 iptables 模拟各种网络异常#

连接被拒绝#

通过下面的抓包信息可以观察到,使用 iptables –reject-with tcp-reset 的设置拒绝连接,其效果与访问不存在的端口一样,服务器收到 SYN 包后会发送 RST-ACK 来拒绝连接。

# 使用 --reject-with tcp-reset 拒绝连接
iptables -A INPUT -p tcp --dport 8000 -j REJECT  --reject-with tcp-reset

# 设置规则的端口抓包
tcpdump -nn -i lo tcp port 8000
09:31:28.648895 IP 127.0.0.1.58742 > 127.0.0.1.8000: Flags [S], seq 812934796, win 65495, options [mss 65495,sackOK,TS val 1025394791 ecr 0,nop,wscale 7], length 0
09:31:28.648903 IP 127.0.0.1.8000 > 127.0.0.1.58742: Flags [R.], seq 0, ack 812934797, win 0, length 0

# 无监听端口抓包
tcpdump -nn -i lo tcp port 8001
09:50:31.493573 IP 127.0.0.1.55880 > 127.0.0.1.8001: Flags [S], seq 658864455, win 65495, options [mss 65495,sackOK,TS val 1026538482 ecr 0,nop,wscale 7], length 0
09:50:31.493584 IP 127.0.0.1.8001 > 127.0.0.1.55880: Flags [R.], seq 0, ack 658864456, win 0, length 0

ICMP Destination Unreachable Message#

活到老学到老,TCP拒绝连接也可以使用 ICMP 协议的 Destination Unreachable Message,这甚至是 iptables 的默认行为。

ICMP Destination Unreachable Message 有6中类型,其中第四个为 port unreachable,这里是参考文档

拒绝 TCP 连接通过上面的 RST-ACK 返回就可以实现,为什么还有一个通过 ICMP 拒绝的方式呢?

网络上给出的解释是在 TCP 模块不可用或者在网关层面出现无法回包的情况下,通过向回发送一个 ICMP 消息来通知对方。

下面上代码:

# 通过 iptables 拒绝连接,使用默认的拒绝方式
iptables -A INPUT -p tcp --dport 8000 -j REJECT

# 列出规则
iptables -L --line-numbers -n

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8000 reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

可以看到 REJECT 规则中最后标明:“reject-with icmp-port-unreachable”。

抓包结果如下:

tcpdump -vvX -nn -i lo

10:47:02.368809 IP (tos 0x0, ttl 64, id 48242, offset 0, flags [DF], proto TCP (6), length 60)
    127.0.0.1.58770 > 127.0.0.1.8000: Flags [S], cksum 0xfe30 (incorrect -> 0xc0dc), seq 3041083996, win 65495, options [mss 65495,sackOK,TS val 1028871519 ecr 0,nop,wscale 7], length 0
        0x0000:  4500 003c bc72 4000 4006 8047 7f00 0001  E..<.r@.@..G....
        0x0010:  7f00 0001 e592 1f40 b543 425c 0000 0000  .......@.CB\....
        0x0020:  a002 ffd7 fe30 0000 0204 ffd7 0402 080a  .....0..........
        0x0030:  3d53 555f 0000 0000 0103 0307            =SU_........
10:47:02.368823 IP (tos 0xc0, ttl 64, id 31398, offset 0, flags [none], proto ICMP (1), length 88)
    127.0.0.1 > 127.0.0.1: ICMP 127.0.0.1 tcp port 8000 unreachable, length 68
        IP (tos 0x0, ttl 64, id 48242, offset 0, flags [DF], proto TCP (6), length 60)
    127.0.0.1.58770 > 127.0.0.1.8000: Flags [S], cksum 0xfe30 (incorrect -> 0xc0dc), seq 3041083996, win 65495, options [mss 65495,sackOK,TS val 1028871519 ecr 0,nop,wscale 7], length 0
        0x0000:  45c0 0058 7aa6 0000 4001 013d 7f00 0001  E..Xz...@..=....
        0x0010:  7f00 0001 0303 bdd9 0000 0000 4500 003c  ............E..<
        0x0020:  bc72 4000 4006 8047 7f00 0001 7f00 0001  .r@.@..G........
        0x0030:  e592 1f40 b543 425c 0000 0000 a002 ffd7  ...@.CB\........
        0x0040:  fe30 0000 0204 ffd7 0402 080a 3d53 555f  .0..........=SU_
        0x0050:  0000 0000 0103 0307                      ........

由于回包是 ICMP 协议,因此这里抓取了全部协议的包。

可以看到客户端向服务器端发送 SYN 之后,服务器端没有回复 TCP 包,而是回复了一个 ICMP 包,内容是 8000 端口不可达,并附上了客户端的 SYN 包内容。

连接超时#

通过下面命令可以设置 iptables 收到 SYN 包之后不做任何响应。

iptables -A INPUT -p tcp --dport 8000 -j DROP

设置后抓包就可以看到服务端收到 SYN 包不会做任何响应,客户端在一段时间后超时。

curl 可以通过参数设置连接超时时间,时测试速度更快:

curl -v --connect-timeout 2 http://localhost:8000
* About to connect() to localhost port 8000 (#0)
*   Trying 127.0.0.1...
* After 998ms connect time, move on!
*   Trying ::1...
* Failed to connect to ::1: Cannot assign requested address
* Failed connect to localhost:8000; Cannot assign requested address
* Closing connection 0
curl: (7) Failed to connect to ::1: Cannot assign requested address

连接重置#

iptables 可以在收到特定特征的 TCP 包后进行阻断,由此可以模拟在收到客户端 ACK 后立即发送 RST 断开连接的情况。

iptables -A INPUT -p tcp --tcp-flags ACK ACK --dport 8000 -j REJECT --reject-with tcp-reset

通过抓包可以观察到 RST 包发送的情况:

tcpdump -nn -i lo tcp port 8000

12:34:02.244932 IP 127.0.0.1.58782 > 127.0.0.1.8000: Flags [S], seq 2894986813, win 65495, options [mss 65495,sackOK,TS val 1035056753 ecr 0,nop,wscale 7], length 0
12:34:02.244949 IP 127.0.0.1.8000 > 127.0.0.1.58782: Flags [S.], seq 2949772306, ack 2894986814, win 65483, options [mss 65495,sackOK,TS val 1035056753 ecr 1035056753,nop,wscale 7], length 0
12:34:02.244960 IP 127.0.0.1.58782 > 127.0.0.1.8000: Flags [.], ack 1, win 512, options [nop,nop,TS val 1035056753 ecr 1035056753], length 0
12:34:02.244965 IP 127.0.0.1.8000 > 127.0.0.1.58782: Flags [R], seq 2949772307, win 0, length 0
12:34:03.298691 IP 127.0.0.1.8000 > 127.0.0.1.58782: Flags [S.], seq 2949772306, ack 2894986814, win 65483, options [mss 65495,sackOK,TS val 1035057807 ecr 1035056753,nop,wscale 7], length 0
12:34:03.298712 IP 127.0.0.1.58782 > 127.0.0.1.8000: Flags [R], seq 2894986814, win 0, length 0

可以观察到由于客户端发给服务器端的第三次握手 ACK 包被拦截,iptables 直接发送了 RST 包给客户端,此时服务器端由于没有收到客户端的 ACK,后面又尝试重新发送了 SYN-ACK 包给客户端,由于连接被重置,客户端回复了 RST 给服务器端。

跟上面一样,iptables 默认也可以通过 ICMP Port Unreachable Message 来重置连接,实测有效。

连接后丢包#

在 ACK 后丢弃数据包则连接可以正常建立,但收到数据包后不会回复客户端。

iptables -A INPUT -p tcp --tcp-flags ACK ACK --dport 8000 -j DROP

使用 curl 访问时可以看到 curl 认为连接已经建立成功,会一直卡在等待服务器返回的状态中,由于连接已经建立,这时 curl 的 –connect-timeout 参数无法控制等待数据包返回的时间了。

curl -v --connect-timeout 2 http://localhost:8000

* About to connect() to localhost port 8000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:8000
> Accept: */*
>

使用 –max-time 可以控制 curl 整体的请求时间:

curl -v --max-time 2 http://localhost:8000

* About to connect() to localhost port 8000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:8000
> Accept: */*
>
* Operation timed out after 2004 milliseconds with 0 out of -1 bytes received
* Closing connection 0
curl: (28) Operation timed out after 2004 milliseconds with 0 out of -1 bytes received

使用下面的 iptables 规则达到的效果类似,只不过服务器端还是会处理请求,但是请求无法返回给客户端。

iptables -A OUTPUT -p tcp --tcp-flags SYN,ACK ACK --sport 8000 -j DROP

这里的意思是当 tcp 包的源端口为 8000 (服务器端回复的包)时,检查 SYN 和 ACK 两个标志位,当 ACK 为 1 而 SYN 为 0 时,丢弃数据包。

之所以这样设置是因为在建立连接阶段,服务器会回复 SYN-ACK 包,而在建立连接后,收到客户端的数据包时,服务器会回复 ACK 包。

收到HTTP请求后重置连接#

在测试中观察到 curl 发送请求数据时带有 PSH 标记,所以通过下面的命令可以模拟服务器端在收到客户端请求后,不进行任何返回,通过 RST 包重置连接。

iptables -A INPUT -p tcp --tcp-flags PSH PSH --dport 8000 -j REJECT --reject-with tcp-reset

这种模式与 WAF 或 IPS 通过 Reset 包阻断恶意 HTTP 请求时的模式是一样的。

tcpdump -nn -i lo tcp port 8000

03:37:45.389890 IP 127.0.0.1.58822 > 127.0.0.1.8000: Flags [S], seq 540690391, win 65495, options [mss 65495,sackOK,TS val 1043996057 ecr 0,nop,wscale 7], length 0
03:37:45.389933 IP 127.0.0.1.8000 > 127.0.0.1.58822: Flags [S.], seq 4145659323, ack 540690392, win 65483, options [mss 65495,sackOK,TS val 1043996057 ecr 1043996057,nop,wscale 7], length 0
03:37:45.389947 IP 127.0.0.1.58822 > 127.0.0.1.8000: Flags [.], ack 1, win 512, options [nop,nop,TS val 1043996058 ecr 1043996057], length 0
03:37:45.390102 IP 127.0.0.1.58822 > 127.0.0.1.8000: Flags [P.], seq 1:79, ack 1, win 512, options [nop,nop,TS val 1043996058 ecr 1043996057], length 78
03:37:45.390110 IP 127.0.0.1.8000 > 127.0.0.1.58822: Flags [R], seq 4145659324, win 0, length 0

这种模式也可以通过代码来进行模拟,下面是简单的Python代码示例:

import struct
import sys
import socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', int(sys.argv[1]))
server_socket.bind(server_address)
server_socket.listen(1)

client_socket, client_address = server_socket.accept()
request = client_socket.recv(1024).decode("utf-8")

# 通过 reset 关闭连接
l_onoff = 1
l_linger = 0
client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', l_onoff, l_linger))
client_socket.close()

server_socket.close()

挥手包的拦截#

三次握手四次挥手,如果用 iptables 拦截挥手包会出现什么情况呢?

事实证明,在挥手阶段发送 Reset 包或者丢弃挥手包,对于 HTTP 的应用程序没有任何影响,程序会认为连接已经正常关闭。

实际抓包时会发现如果挥手包被丢弃,内核会尝试重发。

随机丢包#

下面命令使用 iptables 让目标端口为 8000 的数据包随机 5% 的概率丢包。

iptables -A INPUT -p tcp --dport 8000 -m statistic --mode random --probability 0.05 -j DROP

通过 tcpdump 抓包可以观察到因为丢包,某次请求的 SYN 包发送了三次:

tcpdump -nn -i lo tcp port 8000

04:24:54.832660 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [S], seq 4205020129, win 65495, options [mss 65495,sackOK,TS val 1105110441 ecr 0,nop,wscale 7], length 0
04:24:55.894105 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [S], seq 4205020129, win 65495, options [mss 65495,sackOK,TS val 1105111503 ecr 0,nop,wscale 7], length 0
04:24:57.944093 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [S], seq 4205020129, win 65495, options [mss 65495,sackOK,TS val 1105113553 ecr 0,nop,wscale 7], length 0
04:24:57.944204 IP 127.0.0.1.8000 > 127.0.0.1.59800: Flags [S.], seq 1737970132, ack 4205020130, win 65483, options [mss 65495,sackOK,TS val 1105113553 ecr 1105113553,nop,wscale 7], length 0
04:24:57.944239 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [.], ack 1, win 512, options [nop,nop,TS val 1105113553 ecr 1105113553], length 0
04:24:57.944388 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [P.], seq 1:79, ack 1, win 512, options [nop,nop,TS val 1105113553 ecr 1105113553], length 78
04:24:57.944425 IP 127.0.0.1.8000 > 127.0.0.1.59800: Flags [.], ack 79, win 511, options [nop,nop,TS val 1105113553 ecr 1105113553], length 0
04:24:57.945561 IP 127.0.0.1.8000 > 127.0.0.1.59800: Flags [P.], seq 1:64, ack 79, win 512, options [nop,nop,TS val 1105113554 ecr 1105113553], length 63
04:24:57.945623 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [.], ack 64, win 512, options [nop,nop,TS val 1105113554 ecr 1105113554], length 0
04:24:57.945923 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [F.], seq 79, ack 64, win 512, options [nop,nop,TS val 1105113555 ecr 1105113554], length 0
04:24:57.946421 IP 127.0.0.1.8000 > 127.0.0.1.59800: Flags [F.], seq 64, ack 80, win 512, options [nop,nop,TS val 1105113555 ecr 1105113555], length 0
04:24:57.946445 IP 127.0.0.1.59800 > 127.0.0.1.8000: Flags [.], ack 65, win 512, options [nop,nop,TS val 1105113555 ecr 1105113555], length 0

由于简单 http 请求的包数量较少,5% 的概率丢包可能要多试几次才能观察到,也可以把概率增大,这样更容易观察。

其它网络异常的模拟#

上面使用 iptables 主要模拟各种丢包或者被拦截的情况,还有一些网速慢或者重传的情况可以使用别的方式模拟。

对于网络的丢包,延迟等模拟也可以通过 netem 工具完成:https://stackoverflow.com/a/615757/775640

今日在网上看到一篇文章,跟我的研究很相似,先记录一下:https://medium.com/@zakharenko/how-to-simulate-network-failures-in-linux-b71ab585e86f

comments powered by Disqus