Extend ovpn-cli set_peer to pass the peer mssfix attribute. Use -1 as
the selftest CLI sentinel for leaving mssfix unchanged, so existing
timeout-only peer updates can keep omitting the netlink attribute.

Add an ovpn test stage that configures mssfix on each side of a peer
pair and verifies the MSS advertised on TCP SYN packets seen on the
tunnel device. This covers both TX-side and RX-side clamping, and also
checks that an invalid non-zero MSS value is rejected.

Signed-off-by: Ralf Lici <[email protected]>
---
 tools/testing/selftests/net/ovpn/ovpn-cli.c   | 19 ++++-
 .../selftests/net/ovpn/test-close-socket.sh   |  4 +-
 tools/testing/selftests/net/ovpn/test-mark.sh |  4 +-
 tools/testing/selftests/net/ovpn/test.sh      | 75 +++++++++++++++++--
 4 files changed, 89 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c 
b/tools/testing/selftests/net/ovpn/ovpn-cli.c
index d40953375c86..ca992a7cee3d 100644
--- a/tools/testing/selftests/net/ovpn/ovpn-cli.c
+++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <inttypes.h>
 #include <stdbool.h>
+#include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
@@ -129,6 +130,7 @@ struct ovpn_ctx {
 
        __u32 keepalive_interval;
        __u32 keepalive_timeout;
+       int mssfix;
 
        enum ovpn_key_direction key_dir;
        enum ovpn_key_slot key_slot;
@@ -732,6 +734,8 @@ static int ovpn_set_peer(struct ovpn_ctx *ovpn)
                    ovpn->keepalive_interval);
        NLA_PUT_U32(ctx->nl_msg, OVPN_A_PEER_KEEPALIVE_TIMEOUT,
                    ovpn->keepalive_timeout);
+       if (ovpn->mssfix >= 0)
+               NLA_PUT_U16(ctx->nl_msg, OVPN_A_PEER_MSSFIX, ovpn->mssfix);
        nla_nest_end(ctx->nl_msg, attr);
 
        ret = ovpn_nl_msg_send(ctx, NULL);
@@ -1730,13 +1734,15 @@ static void usage(const char *cmd)
        fprintf(stderr, "\tmark: socket FW mark value\n");
 
        fprintf(stderr,
-               "* set_peer <iface> <peer_id> <keepalive_interval> 
<keepalive_timeout>: set peer attributes\n");
+               "* set_peer <iface> <peer_id> <keepalive_interval> 
<keepalive_timeout> <mssfix>: set peer attributes\n");
        fprintf(stderr, "\tiface: ovpn interface name\n");
        fprintf(stderr, "\tpeer_id: peer ID of the peer to modify\n");
        fprintf(stderr,
                "\tkeepalive_interval: interval for sending ping messages\n");
        fprintf(stderr,
                "\tkeepalive_timeout: time after which a peer is timed out\n");
+       fprintf(stderr,
+               "\tmssfix: TCP MSS value to clamp SYN packets to (0 disables, 
-1 leaves unchanged)\n");
 
        fprintf(stderr, "* del_peer <iface> <peer_id>: delete peer\n");
        fprintf(stderr, "\tiface: ovpn interface name\n");
@@ -2307,7 +2313,7 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int 
argc, char *argv[])
                }
                break;
        case CMD_SET_PEER:
-               if (argc < 6)
+               if (argc < 7)
                        return -EINVAL;
 
                ovpn->peer_id = strtoul(argv[3], NULL, 10);
@@ -2329,6 +2335,14 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, 
int argc, char *argv[])
                                "keepalive interval value out of range\n");
                        return -1;
                }
+
+               errno = 0;
+               ovpn->mssfix = strtol(argv[6], NULL, 10);
+               if (errno == ERANGE || ovpn->mssfix < -1 ||
+                   ovpn->mssfix > UINT16_MAX) {
+                       fprintf(stderr, "mssfix value out of range\n");
+                       return -1;
+               }
                break;
        case CMD_DEL_PEER:
                if (argc < 4)
@@ -2442,6 +2456,7 @@ int main(int argc, char *argv[])
        memset(&ovpn, 0, sizeof(ovpn));
        ovpn.sa_family = AF_UNSPEC;
        ovpn.cipher = OVPN_CIPHER_ALG_NONE;
+       ovpn.mssfix = -1;
 
        ovpn.cmd = ovpn_parse_cmd(argv[1]);
        if (ovpn.cmd == CMD_INVALID) {
diff --git a/tools/testing/selftests/net/ovpn/test-close-socket.sh 
b/tools/testing/selftests/net/ovpn/test-close-socket.sh
index af1532b4d2da..091c0103bdba 100755
--- a/tools/testing/selftests/net/ovpn/test-close-socket.sh
+++ b/tools/testing/selftests/net/ovpn/test-close-socket.sh
@@ -41,10 +41,10 @@ ovpn_prepare_network() {
                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
+                               ${p} 60 120 -1
                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
+                               tun${p} $((p + OVPN_ID_OFFSET)) 60 120 -1
        done
 }
 
diff --git a/tools/testing/selftests/net/ovpn/test-mark.sh 
b/tools/testing/selftests/net/ovpn/test-mark.sh
index 5a8f47554286..11af23beea2a 100755
--- a/tools/testing/selftests/net/ovpn/test-mark.sh
+++ b/tools/testing/selftests/net/ovpn/test-mark.sh
@@ -54,10 +54,10 @@ ovpn_mark_prepare_network() {
                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
+                               "${p}" 60 120 -1
                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
+                               tun"${p}" $((p + OVPN_ID_OFFSET)) 60 120 -1
        done
 }
 
diff --git a/tools/testing/selftests/net/ovpn/test.sh 
b/tools/testing/selftests/net/ovpn/test.sh
index c06e3135fbef..a0630034351a 100755
--- a/tools/testing/selftests/net/ovpn/test.sh
+++ b/tools/testing/selftests/net/ovpn/test.sh
@@ -49,10 +49,10 @@ ovpn_prepare_network() {
                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
+                               ${p} 60 120 -1
                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
+                               tun${p} $((p + OVPN_ID_OFFSET)) 60 120 -1
        done
 }
 
@@ -142,6 +142,66 @@ ovpn_run_iperf() {
        wait "${iperf_pid}" || return 1
 }
 
+ovpn_run_mssfix_flow() {
+       local filter
+       local iperf_pid
+       local direction="$1"
+       local mssfix="$2"
+       local tcpdump_pid
+
+       filter="tcp and src host 5.5.5.1 and dst host 5.5.5.2"
+       filter="${filter} and tcp[tcpflags] & tcp-syn != 0"
+
+       ovpn_run_bg iperf_pid ip netns exec ovpn_peer1 iperf3 -1 -s
+       sleep 1
+
+       timeout 3s ip netns exec ovpn_peer1 tcpdump --immediate-mode -l -p \
+               -vv -nn -i tun1 -c 1 "${filter}" 2>&1 |
+               grep -iq "mss ${mssfix}" &
+       tcpdump_pid=$!
+       sleep 0.3
+
+       ovpn_cmd_ok "run ${direction} mssfix TCP flow" \
+               ip netns exec ovpn_peer0 iperf3 -t 1 -c 5.5.5.2
+
+       ovpn_cmd_ok "capture ${direction} mssfix TCP SYN" wait "${tcpdump_pid}"
+       ovpn_cmd_ok "finish ${direction} mssfix TCP server" wait "${iperf_pid}"
+}
+
+ovpn_run_mssfix() {
+       local peer0_id=$((1 + OVPN_ID_OFFSET))
+
+       # peer0 will clamp MSS for packets exchanged with peer1
+       ovpn_cmd_ok "set peer0 mssfix for peer 1" \
+               ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 1 \
+                       60 120 900
+
+       ovpn_cmd_fail "reject invalid peer0 mssfix for peer 1" \
+               ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 1 \
+                       60 120 20
+
+       ovpn_cmd_ok "clear peer1 mssfix for peer ${peer0_id}" \
+               ip netns exec ovpn_peer1 ${OVPN_CLI} set_peer tun1 \
+                       "${peer0_id}" 60 120 0
+
+       ovpn_run_mssfix_flow "TX" 900
+
+       ovpn_cmd_ok "clear peer0 mssfix for peer 1" \
+               ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 1 \
+                       60 120 0
+
+       # peer1 will clamp MSS for packets exchanged with peer0
+       ovpn_cmd_ok "set peer1 mssfix for peer ${peer0_id}" \
+               ip netns exec ovpn_peer1 ${OVPN_CLI} set_peer tun1 \
+                       "${peer0_id}" 60 120 901
+
+       ovpn_run_mssfix_flow "RX" 901
+
+       ovpn_cmd_ok "clear peer1 mssfix for peer ${peer0_id}" \
+               ip netns exec ovpn_peer1 ${OVPN_CLI} set_peer tun1 \
+                       "${peer0_id}" 60 120 0
+}
+
 ovpn_run_key_rollover() {
        local p
        local peer_ns
@@ -259,11 +319,11 @@ ovpn_run_timeouts() {
                # Non-fatal: this may fail in some protocol modes.
                ovpn_cmd_mayfail "set peer0 timeout for peer ${p} (non-fatal)" \
                        ip netns exec ovpn_peer0 ${OVPN_CLI} set_peer tun0 \
-                               ${p} 3 3
+                               ${p} 3 3 -1
                peer_ns="ovpn_peer${p}"
                ovpn_cmd_ok "disable timeout on peer${p} while peer0 adjusts \
                        state" ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \
-                       tun${p} $((p + OVPN_ID_OFFSET)) 0 0
+                       tun${p} $((p + OVPN_ID_OFFSET)) 0 0 -1
        done
        # wait for peers to timeout
        sleep 5
@@ -274,7 +334,7 @@ ovpn_run_timeouts() {
                peer_ns="ovpn_peer${p}"
                ovpn_cmd_ok "set peer${p} P2P timeout" \
                        ip netns exec "${peer_ns}" ${OVPN_CLI} set_peer \
-                               tun${p} $((p + OVPN_ID_OFFSET)) 3 3
+                               tun${p} $((p + OVPN_ID_OFFSET)) 3 3 -1
        done
        sleep 5
 }
@@ -293,9 +353,9 @@ trap ovpn_stage_err ERR
 
 ktap_print_header
 if [ "${OVPN_FLOAT}" == "1" ]; then
-       ktap_set_plan 13
+       ktap_set_plan 14
 else
-       ktap_set_plan 12
+       ktap_set_plan 13
 fi
 
 ovpn_cleanup
@@ -307,6 +367,7 @@ ovpn_run_stage "run LAN traffic behind peer1" 
ovpn_run_lan_traffic
 [ "${OVPN_FLOAT}" == "1" ] && ovpn_run_stage "run floating peer checks" \
        ovpn_run_float_mode
 ovpn_run_stage "run iperf throughput" ovpn_run_iperf
+ovpn_run_stage "run mssfix TCP SYN clamp" ovpn_run_mssfix
 ovpn_run_stage "run key rollout" ovpn_run_key_rollover
 ovpn_run_stage "query peers" ovpn_run_queries
 ovpn_run_stage "query missing peer fails" ovpn_query_peer_missing
-- 
2.54.0



_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to