blob: 7c1d56e9c525d597f2f314b1f45b2c9238eaa5b0 (
plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2020-2025 OpenVPN, Inc.
#
# Author: Ralf Lici <ralf@mandelbit.com>
# Antonio Quartulli <antonio@openvpn.net>
#set -x
set -eE
MARK=1056
MARK_DROP_COUNTER=0
source ./common.sh
ovpn_test_finished=0
ovpn_test_exit() {
ovpn_cleanup
modprobe -r ovpn || true
if [ "${ovpn_test_finished}" -eq 0 ]; then
ktap_print_totals
fi
}
ovpn_mark_prepare_network() {
local p
local peer_ns
for p in $(seq 0 "${OVPN_NUM_PEERS}"); do
ovpn_cmd_ok "create namespace peer${p}" ovpn_create_ns "${p}"
done
for p in $(seq 0 3); do
ovpn_cmd_ok "configure peer${p} namespace" ovpn_setup_ns \
"${p}" 5.5.5.$((p + 1))/24
done
ovpn_cmd_ok "create server-side multi-peer with fwmark" \
ip netns exec ovpn_peer0 "${OVPN_CLI}" new_multi_peer tun0 1 \
ASYMM "${OVPN_UDP_PEERS_FILE}" "${MARK}"
for p in $(seq 1 3); do
ovpn_cmd_ok "install server key for peer ${p}" \
ip netns exec ovpn_peer0 "${OVPN_CLI}" new_key tun0 \
"${p}" 1 0 "${OVPN_ALG}" 0 data64.key
done
for p in $(seq 1 3); do
ovpn_cmd_ok "register peer${p} in overlay" ovpn_add_peer "${p}"
done
for p in $(seq 1 3); do
peer_ns="ovpn_peer${p}"
ovpn_cmd_ok "set peer0 timeout for peer ${p}" \
ip netns exec ovpn_peer0 "${OVPN_CLI}" set_peer tun0 \
"${p}" 60 120
ovpn_cmd_ok "set peer${p} timeout for peer ${p}" \
ip netns exec "${peer_ns}" "${OVPN_CLI}" set_peer \
tun"${p}" $((p + OVPN_ID_OFFSET)) 60 120
done
}
ovpn_mark_run_baseline_traffic() {
local p
for p in $(seq 1 3); do
ovpn_cmd_ok "send baseline traffic to peer ${p}" \
ip netns exec ovpn_peer0 ping -qfc 100 -w 3 \
5.5.5.$((p + 1))
done
}
ovpn_mark_add_drop_rule() {
ovpn_log "Adding an nftables drop rule based on mark value ${MARK}"
ovpn_cmd_ok "flush nft ruleset" ip netns exec ovpn_peer0 nft flush \
ruleset
ovpn_cmd_ok "create nft filter table" ip netns exec ovpn_peer0 nft \
"add table inet filter"
ovpn_cmd_ok "create nft filter output chain" \
ip netns exec ovpn_peer0 nft "add chain inet filter output { \
type filter hook output priority 0; policy accept; }"
ovpn_cmd_ok "add nft drop rule for mark ${MARK}" \
ip netns exec ovpn_peer0 nft add rule inet filter output \
meta mark == "${MARK}" \
counter drop
MARK_DROP_COUNTER=$(ip netns exec ovpn_peer0 nft list chain inet \
filter output | sed -n 's/.*packets \([0-9]*\).*/\1/p')
if [ -z "${MARK_DROP_COUNTER}" ]; then
printf '%s\n' "unable to read nft drop counter"
return 1
fi
}
ovpn_mark_verify_drop_traffic() {
local p
local ping_output
local lost_packets
local total_count
for p in $(seq 1 3); do
if ping_output=$(ip netns exec ovpn_peer0 ping -qfc 100 -w 1 \
5.5.5.$((p + 1)) 2>&1); then
printf '%s\n' "expected ping to peer ${p} to fail \
after nft drop rule"
return 1
fi
ovpn_log "${ping_output}"
lost_packets=$(echo "${ping_output}" | \
awk '/packets transmitted/ { print $1 }')
if [ -z "${lost_packets}" ]; then
printf '%s\n' "unable to parse lost packets for peer \
${p}"
return 1
fi
MARK_DROP_COUNTER=$((MARK_DROP_COUNTER + lost_packets))
done
total_count=$(ip netns exec ovpn_peer0 nft list chain inet filter \
output | sed -n 's/.*packets \([0-9]*\).*/\1/p')
if [ -z "${total_count}" ]; then
printf '%s\n' "unable to read final nft drop counter"
return 1
fi
if [ "${MARK_DROP_COUNTER}" -ne "${total_count}" ]; then
printf '%s\n' "expected ${MARK_DROP_COUNTER} drops, got \
${total_count}"
return 1
fi
}
ovpn_mark_remove_drop_rule() {
ovpn_log "Removing the drop rule"
ovpn_cmd_ok "flush nft ruleset" ip netns exec ovpn_peer0 nft flush \
ruleset
}
ovpn_mark_verify_traffic_recovery() {
local p
sleep 1
for p in $(seq 1 3); do
ovpn_cmd_ok "send recovery traffic to peer ${p}" \
ip netns exec ovpn_peer0 ping -qfc 100 -w 3 \
5.5.5.$((p + 1))
done
}
trap ovpn_test_exit EXIT
trap ovpn_stage_err ERR
ktap_print_header
ktap_set_plan 6
ovpn_cleanup
modprobe -q ovpn || true
ovpn_run_stage "setup marked network topology" ovpn_mark_prepare_network
ovpn_run_stage "run baseline traffic" ovpn_mark_run_baseline_traffic
ovpn_run_stage "install nft mark drop rule" ovpn_mark_add_drop_rule
ovpn_run_stage "drop marked traffic and count packets" \
ovpn_mark_verify_drop_traffic
ovpn_run_stage "remove nft drop rule" ovpn_mark_remove_drop_rule
ovpn_run_stage "traffic recovers after drop removal" \
ovpn_mark_verify_traffic_recovery
ovpn_test_finished=1
ktap_finished
|