libreswan

#!/bin/bash
#


LIP="172.16.0.1"
RIP="172.16.0.2"
LIP6="2001:192:168:211::64"
RIP6="2001:192:168:211::65"

IPERF_FILE="/tmp/iperf.log"
TCPDUMP_FILE="/tmp/tcpdump.log"

IPSEC_LIBRESWAN_DIR=$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)
. $IPSEC_LIBRESWAN_DIR/common-ipsec.sh

IPSEC_CONFIG_DIR="/etc/ipsec.d"
IPSEC_CONN="mytunnel"
IPSEC_MYTUNNEL_CONF="$IPSEC_CONFIG_DIR/${IPSEC_CONN}.conf"
IPSEC_TMP_CONF="/tmp/${IPSEC_CONN}.conf"
CONNECT_TIMEOUT=3

__foo_copied=()
# use a static file to avoid creating endless temp files.
__FOO="/tmp/foo.sh"
function __foo_copy() {
if [[ "${__foo_copied[@]}" =~ $remote ]]; then
return
fi
local i
for i in _longopt _parse_help _parse_usage; do unset -f $i ; done
declare -p PCI_MAP > $__FOO
declare -p TRAFFIC_INFO >> $__FOO
set | grep -Ev "^(BASH|SHELLOPTS|UID|EUID|PPID|_OVS_VSCTL|IS_BF_HOST|COVFILE|COVERR)" >> $__FOO
echo ". /etc/os-release" >> $__FOO
scp2 $__FOO $remote:/tmp/
__foo_copied+=($remote)
}

function scp2() {
scp -q -o ConnectTimeout=$CONNECT_TIMEOUT "$@"
}

function ssh2() {
__USING_REMOTE_SERVER=1
ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o BatchMode=yes -o ConnectTimeout=$CONNECT_TIMEOUT "$@"
local rc=$?
if [ $rc -eq 255 ]; then
debug "SSH connection $1 rc 255"
fi
return $rc
}

function __on_remote() {
local remote=$1
ssh2 $remote "[ -n $CONFIG ] && . $CONFIG ; ${@:2}"
}

function on_remote() {
[ -z "$REMOTE_SERVER" ] && fail "No remote server configured"
__on_remote $REMOTE_SERVER "$@"
}

function __on_remote_exec() {
local remote=$1
__foo_copy
ssh2 $remote ". $__FOO; ${@:2}"
}

function on_remote_exec() {
[ -z "$REMOTE_SERVER" ] && fail "No remote server configured"
__on_remote_exec $REMOTE_SERVER "$@"
}

function ipsec_dump_hostkeys() {
ipsec showhostkey --dump | grep -o "RSA keyid: [^ ]*" | awk {'print $3'}
}

# get the first rsa key
function ipsec_get_hostkey() {
ipsec_dump_hostkeys | head -1
}

function __ipsec_init_keys() {
local dump=`ipsec showhostkey --dump 2>/dev/null`
if [ $? == 1 ] || [ -z "$dump" ]; then
ipsec initnss
ipsec newhostkey
fi
}

function ipsec_get_left_key() {
local rsaid=$1
ipsec showhostkey --left --rsaid $rsaid
}

#note: runs on remote
function ipsec_get_right_key() {
local rsaid=$1
on_remote ipsec showhostkey --right --rsaid $rsaid
}

function ipsec_setup_start() {
log "Start ipsec service"
ipsec setup start
on_remote ipsec setup start
}

function ipsec_setup_stop() {
log "Stop ipsec service"
ipsec setup stop
on_remote ipsec setup stop
}

function ipsec_trafficstatus() {
local conn=$1
[ -z "$conn" ] && ipsec trafficstatus
[ -n "$conn" ] && ipsec trafficstatus | grep -w $conn
}

function ipsec_config_conn() {
local local_offload_mode=${1:-"no-offload"}
local remote_offload_mode=${2:-"no-offload"}
__ipsec_init_keys
local key=`ipsec_get_hostkey`

on_remote_exec __ipsec_init_keys
local remote_key=`on_remote_exec ipsec_get_hostkey`

if [ -z "$key" ]; then
fail "Missing ipsec local host key"
fi

if [ -z "$remote_key" ]; then
fail "Missing ipsec remote host key"
fi

echo "key: $key"
echo "remote key: $remote_key"

log "Create ipsec config"
ipsec_create_conf $local_offload_mode $remote_offload_mode
log "Copy ipsec config to remote"
scp2 $IPSEC_TMP_CONF $REMOTE_SERVER:$IPSEC_MYTUNNEL_CONF
}

function ipsec_create_conf() {
local local_offload="$1"
local remote_offload="$2"
local nic_offload="no"
local leftsig=`ipsec_get_left_key $key`
local rightsig=`ipsec_get_right_key $remote_key`

echo "left sig: $leftsig"
echo "right sig: $rightsig"

[ -z "$leftsig" ] && fail "Missing ipsec left sig"
[ -z "$rightsig" ] && fail "Missing ipsec right sig"

if [ "$local_offload" == "crypto" ]; then
nic_offload="yes"
elif [ "$local_offload" == "packet" ]; then
nic_offload="packet"
fi

echo "
conn $IPSEC_CONN
leftid=@west
left=$LIP
$leftsig
rightid=@east
right=$RIP
$rightsig
authby=rsasig
auto=ondemand
type=transport
nic-offload=$nic_offload" > $IPSEC_MYTUNNEL_CONF

nic_offload="no"
if [ "$remote_offload" == "crypto" ]; then
nic_offload="yes"
elif [ "$remote_offload" == "packet" ]; then
nic_offload="packet"
fi
echo "

conn $IPSEC_CONN
leftid=@west
left=$LIP
$leftsig
rightid=@east
right=$RIP
$rightsig
authby=rsasig
auto=ondemand
type=transport
nic-offload=$nic_offload" > $IPSEC_TMP_CONF

}

function ipsec_config_setup() {
local local_offload_mode=${1:-"no-offload"}
local remote_offload_mode=${2:-"no-offload"}
ipsec_setup_stop
ip a r dev $NIC $LIP/24
ip l s dev $NIC up
on_remote "ip a r dev $NIC $RIP/24
ip l s dev $NIC up"
ipsec_config_conn $local_offload_mode $remote_offload_mode
ipsec_setup_start
ipsec auto --add $IPSEC_CONN || fail "Failed to add ipsec tunnel"
ipsec auto --start $IPSEC_CONN || fail "Failed to start ipsec tunnel"
}

function ipsec_clear_setup() {
ipsec auto --down $IPSEC_CONN
ipsec auto --delete $IPSEC_CONN
ipsec_setup_stop
}

function ipsec_verify_trafficstatus() {
local in=`ipsec_trafficstatus $IPSEC_CONN | grep -o "inBytes=[0-9]\+" | cut -d= -f2`
local out=`ipsec_trafficstatus $IPSEC_CONN | grep -o "outBytes=[0-9]\+" | cut -d= -f2`

if [ -z "$in" ] || [ "$in" == 0 ]; then
err "Mssing inBytes"
fi

if [ -z "$out" ] || [ "$out" == 0 ]; then
err "Mssing outBytes"
fi
}


function ipsec_flush_local() {
local dev=${1:-"$NIC"}
log "Flush xfrm state and policy"
ip xfrm state flush
ip xfrm policy flush
ip address flush $dev
}

function ipsec_flush_remote() {
local dev=${1:-"$NIC"}
log "Flush remote xfrm state and policy"
on_remote "ip xfrm state flush
ip xfrm policy flush
ip address flush $dev"
}

function ipsec_cleanup_on_both_sides() {
local dev=${1:-"$NIC"}
ipsec_flush_local $dev
ipsec_flush_remote $dev
}

function kill_iperf() {
on_remote killall -9 iperf3 &>/dev/null
killall -9 iperf3 &>/dev/null
}

function start_iperf_server_on_remote() {
on_remote "iperf3 -s -D"
sleep 2
}

function start_iperf_server() {
iperf3 -s -D
sleep 2
}

function change_mtu_on_both_sides() {
local mtu_val=${1}
local local_dev=${2:-"$NIC"}
local remote_dev=${3:-"$REMOTE_NIC"}
ip link set $local_dev mtu $mtu_val
on_remote ip link set $remote_dev mtu $mtu_val
}

function cleanup_test() {
local mtu=${1:-1500}
local trusted_vfs=${2:-"no_trusted_vfs"}
local nic="$NIC"
local remote_nic="$REMOTE_NIC"

if [[ "$trusted_vfs" == "trusted_vfs" ]]; then
nic="$VF"
remote_nic="$VF"
fi

kill_iperf
ipsec_cleanup_on_both_sides
change_mtu_on_both_sides $mtu $nic $remote_nic
rm -f $IPERF_FILE $TCPDUMP_FILE
}

function cleanup_crypto() {
cleanup_test
}


function cleanup() {
ipsec_clear_setup
cleanup_crypto
}

function fail_if_err() {
exit 1
}

function fail() {
exit 1
}

function title() {
echo -e $@
}

function verify_have_traffic() {
local pid=$1
wait $pid
local rc=$?
if [[ $rc -eq 0 ]]; then
:
elif [[ $rc -eq 124 ]]; then
err "Expected to see packets"
else
err "Tcpdump failed"
fi
}

#run_traffic ipv4/ipv6 [udp|tcp|icmp]
function run_traffic() {
local IP_PROTO="$1"
local NET_PROTO="$2"
local trusted_vfs=${3:-"no_trusted_vfs"}
local IPERF_EXTRA=""
local nic=""

if [[ $trusted_vfs == "trusted_vfs" ]]; then
nic=$VF
else
nic=$NIC
fi

if [[ "$NET_PROTO" == "tcp" ]]; then
:
elif [[ "$NET_PROTO" == "udp" ]]; then
IPERF_EXTRA="-u"
elif [[ "$NET_PROTO" == "icmp" ]]; then
:
else
err "Wrong arg for function run_traffic"
fi

local t=10

title "Run $NET_PROTO traffic"
rm -f $TCPDUMP_FILE $IPERF_FILE
if [[ "$NET_PROTO" != "icmp" ]]; then
start_iperf_server
fi
# please notice the no filters on the tcpdump since ipsec encrypt the packets and using crypto offload
# will require turning TSO/GRO off in some cases in order to capture the expected traffic which will not
# represent the use case.
timeout $t tcpdump -qnnei $nic -c 5 -w $TCPDUMP_FILE &
local upid=$!
if [[ "$NET_PROTO" == "icmp" ]]; then
if [[ "$IP_PROTO" == "ipv4" ]]; then
(on_remote ping $LIP -q -c 10 -i 0.1 -w 3) || err "ping failed"
else
(on_remote ping $LIP6 -q -c 10 -i 0.1 -w 3) || err "ping failed"
fi
else
if [[ "$IP_PROTO" == "ipv4" ]]; then
(on_remote timeout $((t+2)) iperf3 -c $LIP $IPERF_EXTRA -b 2G > $IPERF_FILE) || err "iperf3 failed"
else
(on_remote timeout $((t+2)) iperf3 -c $LIP6 $IPERF_EXTRA -b 2G > $IPERF_FILE) || err "iperf3 failed"
fi
fi
if [ $TEST_FAILED == 1 ]; then
kill $upid 2>/dev/null
wait $upid 2>/dev/null
fi
fail_if_err
title "Verify $NET_PROTO traffic on $nic"
verify_have_traffic $upid
}

function run_test() {
cleanup
ipsec_config_setup "crypto" "no-offload"
run_traffic ipv4 icmp
ipsec_verify_trafficstatus
}


function run_test1(){
ipsec_config_setup "packet" "no-offload"
run_traffic ipv4 icmp
}
function run_test2(){
ipsec_config_setup "no-offload" "no-offload"
run_traffic ipv4 icmp
}

echo "==========================================="
run_test
echo "==========================================="
cleanup
run_test1
echo "==========================================="
cleanup
run_test2
echo "==========================================="

posted on 2025-04-02 23:20  vanness_205  阅读(25)  评论(0)    收藏  举报