1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/bin/bash
# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
. $NFT_TEST_LIBRARY_FILE
cleanup()
{
for i in $C $S;do
kill $(ip netns pid $i) 2>/dev/null
ip netns del $i
done
}
trap cleanup EXIT
rnd=$(mktemp -u XXXXXXXX)
C="ratelimit-client-$rnd"
S="ratelimit-server-$rnd"
ip_sc=10.167.1.1
ip_cs=10.167.1.2
ip1_cs=10.167.1.3
ip netns add $S
ip netns add $C
ip link add s_c netns $S type veth peer name c_s netns $C
ip -net $S link set s_c up
ip -net $C link set c_s up
ip -net $S link set lo up
ip -net $C link set lo up
ip -net $S addr add ${ip_sc}/24 dev s_c
ip -net $C addr add ${ip_cs}/24 dev c_s
ip -net $C addr add ${ip1_cs}/24 dev c_s
ip netns exec $C ping ${ip_sc} -c1
assert_pass "topo initialization"
ip netns exec $S $NFT -f - <<EOF
table ip filter {
set icmp1 {
type ipv4_addr
size 65535
flags dynamic,timeout
}
set http1 {
type inet_service . ipv4_addr
size 65535
flags dynamic
}
chain input {
type filter hook input priority filter; policy accept;
ip protocol icmp counter jump in_icmp
ip protocol tcp counter jump in_tcp
}
chain in_tcp {
iifname "s_c" tcp dport 80 ct state new add @http1 { tcp dport . ip saddr limit rate over 1/minute burst 5 packets } counter reject
iifname "s_c" tcp dport 80 counter accept
}
chain in_icmp {
iifname "s_c" ip protocol icmp counter update @icmp1 { ip saddr timeout 3s limit rate 1/second burst 5 packets } counter accept
iifname "s_c" ip protocol icmp counter reject
}
}
EOF
assert_pass "Apply ruleset"
# icmp test
ip netns exec $C ping -W 1 ${ip_sc} -c 5 -f -I ${ip_cs} | grep -q '5 received'
assert_pass "saddr1, burst 5 accept"
ip netns exec $C ping -W 1 ${ip_sc} -c 5 -f -I ${ip1_cs} | grep -q '5 received'
assert_pass "saddr2, burst 5 accept"
ip netns exec $C ping -W 1 ${ip_sc} -c 1 -f -I ${ip_cs} | grep -q '1 received'
assert_fail "saddr1, burst 5 up to limit, reject"
sleep 3
ip netns exec $C ping -W 1 ${ip_sc} -c 5 -f -I ${ip_cs} | grep -q '5 received'
assert_pass "saddr1, element timeout,burst 5 pass again"
ip netns exec $C ping -W 1 ${ip_sc} -c 1 -f -I ${ip_cs} | grep -q '1 received'
assert_fail "saddr1, burst 5 up to limit"
ip netns exec $C ping -W 1 ${ip_sc} -c 6 -i 1 -I ${ip1_cs} | grep -q '6 received'
assert_pass "saddr2, 6s test, limit rate 1/second accept"
ip netns exec $C ping -W 1 ${ip_sc} -c 4 -f -I ${ip1_cs} | grep -q '4 received'
assert_pass "saddr2, burst 4 accept"
sleep 2
ip netns exec $C ping -W 1 ${ip_sc} -c 2 -f -I ${ip1_cs} | grep -q '2 received'
assert_pass "saddr2, burst 2 sleep 2, accept"
sleep 2
ip netns exec $C ping -W 1 ${ip_sc} -c 2 -f -I ${ip1_cs} | grep -q '2 received'
assert_pass "saddr2, burst 2 sleep 2, accept"
ip netns exec $C ping -W 1 ${ip_sc} -c 1 -f -I ${ip1_cs} | grep -q '1 received'
assert_fail "saddr2, limit rate 1/second up to limit, reject"
# tcp test
ip netns exec $S socat TCP-LISTEN:80,reuseaddr,fork - > /dev/null &
wait_local_port_listen $S 80 tcp
for port in {1..5};do
ip netns exec $C socat -u - TCP:${ip_sc}:80,connect-timeout=1 <<< 'AAA'
assert_pass "tcp connection burst 5 accept"
done
ip netns exec $C socat -u - TCP:${ip_sc}:80,reuseport,connect-timeout=1 <<< 'AAA'
assert_fail "tcp connection burst 5 up to limit reject"
ip netns exec $S $NFT flush chain filter in_tcp
assert_pass result "flush chain"
ip netns exec $S $NFT flush set filter http1
assert_pass result "flush set"
ip netns exec $S $NFT add rule filter in_tcp iifname s_c tcp dport 80 ct state new add @http1 { tcp dport . ip saddr limit rate over 1/second burst 1 packets} counter reject
assert_pass result "add rule limit rate over 1/second burst 1"
ip netns exec $S $NFT add rule filter in_tcp iifname s_c tcp dport 80 counter accept
sleep 1
ip netns exec $C socat -u - TCP:${ip_sc}:80,reuseport,connect-timeout=1 <<< 'AAA'
assert_pass result "tcp connection limit rate 1/sec burst 1 accept"
ip netns exec $C socat -u - TCP:${ip_sc}:80,reuseport,connect-timeout=1 <<< 'AAA'
assert_fail result "tcp connection limit rate 1/sec burst 1 reject"
sleep 1
ip netns exec $C socat -u - TCP:${ip_sc}:80,reuseport,connect-timeout=1 <<< 'AAA'
assert_pass result "tcp connection limit rate 1/sec burst 1 accept"
|