UDP 數據包似乎在從 Strongswan 到 AWS 雲的 IPsec 隧道中失去 - 連接適用於 Openswan
案例:通過 AWS 雲連接的物聯網設備
IOT 設備位於通過 aws 雲發送所有流量的路由器後面。
IOT 伺服器無法配置,因此不是 AWS 雲的一部分
對於配置,需要向 IOT 設備通知一個 UPD 數據包到埠 xxxxx 以建立管理連接。此 udp 數據包無法直接發送到 AWS 雲
因此,我們需要一個通信伺服器來路由 UDP 數據包:
IOT-server 上的路由無法配置,因此需要將 UDP 數據包發送到 zz.zz.zz.zz
通信伺服器使用 strongswan 執行 debian 10
ipsec.conf:
conn %default mobike=no compress=no authby=secret keyexchange=ike ike=aes128-sha1-modp1024! ikelifetime=8h esp=aes128-sha1-modp1024! lifetime=1h rekeymargin=3m keyingtries=%forever installpolicy=yes dpdaction=restart type=tunnel conn dc-aws1 leftsubnet=zz.zz.zz.zz #local subnet right=vv.vv.vv.vv # AWS Gateway Public IP rightsubnet=xx.xx.0.0/16 #remoye subnet auto=start include /var/lib/strongswan/ipsec.conf.inc
連接工作的以下部分: 標準操作工作正常。
ipsec 連接正在執行(如預期的那樣):
sudo ipsec status Security Associations (1 up, 0 connecting): dc-aws1[3]: ESTABLISHED 11 seconds ago, zz.zz.zz.zz[zz.zz.zz.zz]...vv.vv.vv.vv[vv.vv.vv.vv] dc-aws1{16}: INSTALLED, TUNNEL, reqid 2, ESP in UDP SPIs: cd6dfea5_i 401dc4d5_o dc-aws1{16}: zz.zz.zz.zz/32 = xx.xx.0.0/16 dc-aws1{17}: INSTALLED, TUNNEL, reqid 2, ESP in UDP SPIs: c2507a98_i 9d083aa4_o dc-aws1{17}: zz.zz.zz.zz/32 = xx.xx.0.0/16 sudo ip xfrm policy show src zz.zz.zz.zz/32 dst xx.xx.0.0/16 dir out priority 375423 ptype main tmpl src zz.zz.zz.zz dst vv.vv.vv.vv proto esp spi 0x9d083aa4 reqid 2 mode tunnel src xx.xx.0.0/16 dst zz.zz.zz.zz/32 dir fwd priority 375423 ptype main tmpl src vv.vv.vv.vv dst zz.zz.zz.zz proto esp reqid 2 mode tunnel src xx.xx.0.0/16 dst zz.zz.zz.zz/32 dir in priority 375423 ptype main tmpl src vv.vv.vv.vv dst zz.zz.zz.zz proto esp reqid 2 mode tunnel
Ping 通過 vpn 連接在路由器和通信伺服器之間工作。
如果使用 icmp 數據包,Traceroute 也可以工作。
為了將更新數據包轉發到 IOT 設備,網路地址轉換與 iptables 一起使用
iptables -t nat -I PREROUTING -p udp -s yy.yy.yy.yy --dport xxxxx -j DNAT --to xx.xx.xx.xx
xfrm 策略不適用,如果源是 yy.yy.yy.yy,則也使用源網路地址轉換
iptables -t nat -I POSTROUTING -p udp -s yy.yy.yy.yy --dport xxxxx -j SNAT --to-source zz.zz.zz.zz
還需要轉發規則
iptables -I FORWARD -p udp -d xx.xx.xx.xx --dport xxxxx -j ACCEPT
tcpdump 顯示,udp 數據包到達並被轉發(在這之間,有用於 vpn 連接的活動消息):
sudo tcpdump -n -i any host vv.vv.vv.vv or port xxxxx tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 08:22:48.520734 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: NONESP-encap: isakmp: child_sa inf2[I] 08:22:48.535700 IP vv.vv.vv.vv.4500 > zz.zz.zz.zz.4500: NONESP-encap: isakmp: child_sa inf2[R] 08:22:56.717778 IP yy.yy.yy.yy.54278 > zz.zz.zz.zz.xxxxx: UDP, length 108 08:22:56.717908 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x81f1d489,seq=0x1), length 180 08:23:06.344622 IP yy.yy.yy.yy.46955 > zz.zz.zz.zz.xxxxx: UDP, length 108 08:23:06.344749 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x81f1d489,seq=0x2), length 180 08:23:10.797048 IP yy.yy.yy.yy.33667 > zz.zz.zz.zz.xxxxx: UDP, length 108 08:23:10.797247 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x81f1d489,seq=0x3), length 180 08:23:18.521104 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: NONESP-encap: isakmp: child_sa inf2[I] 08:23:18.536895 IP vv.vv.vv.vv.4500 > zz.zz.zz.zz.4500: NONESP-encap: isakmp: child_sa inf2[R] 08:23:25.423142 IP yy.yy.yy.yy.40703 > zz.zz.zz.zz.xxxxx: UDP, length 108 08:23:25.423271 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x81f1d489,seq=0x4), length 180 08:23:31.756269 IP yy.yy.yy.yy.58584 > zz.zz.zz.zz.xxxxx: UDP, length 108 08:23:31.756378 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x81f1d489,seq=0x5), length 180 ^C 14 packets captured 14 packets received by filter 0 packets dropped by kernel
什麼不起作用:
然而,udp pakets 似乎迷路了。在 aws 的日誌中,隧道中看不到任何流量。此外,沒有數據包到達路由器。
使用 udp 和 tcp 數據包的 Traceroute 不起作用。
當以偵聽模式在通信伺服器上執行 netcat 並從路由器後面連接到它時,可以重現該問題。在 tcp 轉儲中,syn 數據包正在到達,似乎發出了響應,但沒有來自 aws 雲中的通信伺服器的流量到達。來自通信伺服器的 tcpdump 用於此測試:
11:35:06.597736 IP vv.vv.vv.vv.4500 > zz.zz.zz.zz.4500: UDP-encap: ESP(spi=0xcb99370a,seq=0x1), length 100 11:35:06.597736 IP xx.xx.xx.xx.49768 > zz.zz.zz.zz.15952: Flags [S], seq 101710370, win 64240, options [mss 1350,sackOK,TS val 2355221232 ecr 0,nop,wscale 7], length 0 11:35:06.598157 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0xb), length 100 11:35:07.534252 IP vv.vv.vv.vv.4500 > zz.zz.zz.zz.4500: UDP-encap: ESP(spi=0xcb99370a,seq=0x2), length 100 11:35:07.534252 IP xx.xx.xx.xx.49768 > zz.zz.zz.zz.15952: Flags [S], seq 101710370, win 64240, options [mss 1350,sackOK,TS val 2355222233 ecr 0,nop,wscale 7], length 0 11:35:07.534445 IP zz.zz.zz.zz.4500 > vv.vv.vsv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0xc), length 100 11:35:08.561060 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0xd), length 100 11:35:09.559712 IP vv.vv.vv.vv.4500 > zz.zz.zz.zz.4500: UDP-encap: ESP(spi=0xcb99370a,seq=0x3), length 100 11:35:09.559712 IP xx.xx.xx.xx.49768 > zz.zz.zz.zz.15952: Flags [S], seq 101710370, win 64240, options [mss 1350,sackOK,TS val 2355224249 ecr 0,nop,wscale 7], length 0 11:35:09.559908 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0xe), length 100 11:35:11.569079 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0xf), length 100 11:35:13.672232 IP vv.vv.vv.vv.4500 > zz.zz.zz.zz.4500: UDP-encap: ESP(spi=0xcb99370a,seq=0x4), length 100 11:35:13.672232 IP xx.xx.xx.xx.49768 > zz.zz.zz.zz.15952: Flags [S], seq 101710370, win 64240, options [mss 1350,sackOK,TS val 2355228377 ecr 0,nop,wscale 7], length 0 11:35:13.672319 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0x10), length 100 11:35:17.713025 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0x11), length 100 11:35:25.905124 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0x12), length 100 11:35:42.033153 IP zz.zz.zz.zz.4500 > vv.vv.vv.vv.4500: UDP-encap: ESP(spi=0x9a2c6938,seq=0x13), length
我不清楚數據包可能在哪裡失去。歡迎任何有關如何縮小問題範圍的提示
** 更新 **
與此同時,我仔細檢查了配置,但沒有成功。
然後,我切換到了 AWS 測試的 Openswan (2.6.51.5)。
使用 Openswan 數據包按預期到達雲。
我的結論是,Strongswan 與 AWS VPC 不兼容。
如果有關於如何進一步測試的想法,我很樂意進行進一步的測試。
感謝Strongswan 使用者列表上的 Doug Tucker,我也能夠與 Strongswan 建立連接。
我最好的猜測是,這個問題似乎與 xfrm 政策有關。
以下設置(ipsec.conf)對我有用:
config setup # strictcrlpolicy=yes uniqueids = no # Add connections here. conn %default # mobike=no compress=no authby=secret keyexchange=ike ike=aes128-sha1-modp1024! ikelifetime=8h esp=aes128-sha1-modp1024! lifetime=1h # rekeymargin=3m keyingtries=%forever # installpolicy=yes type=tunnel leftauth=psk rightauth=psk dpddelay=10s dpdtimeout=30s dpdaction=restart conn dc-aws1 auto=start left=zx.zx.zx.zx leftid=zz.zz.zz.zz leftsubnet=zx.zx.zx.zx/24 right=vv.vv.vv.vv # AWS Gateway Public IP rightsubnet=xx.xx.0.0/16 #remoye subnet mark=100 leftupdown="/usr/local/bin/aws-updown.sh -ln AWSTunnel1 -ll 169.254.6.2/30 -lr 169.254.6.1/30 -m 100 -r xx.xx.0.0/16"
旁注:vpn 連接已移至虛擬機。zx.zx.zx.zx 是現在執行 vpn 連接的虛擬機的 IP 地址(託管在 zz.zz.zz.zz 上)。
strongswan 使用者列表中也提供了 aws-updown.sh,但也可以在github上找到:
#!/bin/bash while [[ $# > 1 ]]; do case ${1} in -ln|--link-name) TUNNEL_NAME="${2}" TUNNEL_PHY_INTERFACE="${PLUTO_INTERFACE}" shift ;; -ll|--link-local) TUNNEL_LOCAL_ADDRESS="${2}" TUNNEL_LOCAL_ENDPOINT="${PLUTO_ME}" shift ;; -lr|--link-remote) TUNNEL_REMOTE_ADDRESS="${2}" TUNNEL_REMOTE_ENDPOINT="${PLUTO_PEER}" shift ;; -m|--mark) TUNNEL_MARK="${2}" shift ;; -r|--static-route) TUNNEL_STATIC_ROUTE="${2}" shift ;; *) echo "${0}: Unknown argument \"${1}\"" >&2 ;; esac shift done command_exists() { type "$1" >&2 2>&2 } create_interface() { ip link add ${TUNNEL_NAME} type vti local ${TUNNEL_LOCAL_ENDPOINT} remote ${TUNNEL_REMOTE_ENDPOINT} key ${TUNNEL_MARK} ip addr add ${TUNNEL_LOCAL_ADDRESS} remote ${TUNNEL_REMOTE_ADDRESS} dev ${TUNNEL_NAME} ip link set ${TUNNEL_NAME} up mtu 1419 } configure_sysctl() { sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.conf.${TUNNEL_NAME}.rp_filter=2 sysctl -w net.ipv4.conf.${TUNNEL_NAME}.disable_policy=1 sysctl -w net.ipv4.conf.${TUNNEL_PHY_INTERFACE}.disable_xfrm=1 sysctl -w net.ipv4.conf.${TUNNEL_PHY_INTERFACE}.disable_policy=1 } add_route() { IFS=',' read -ra route <<< "${TUNNEL_STATIC_ROUTE}" for i in "${route[@]}"; do ip route add ${i} dev ${TUNNEL_NAME} metric ${TUNNEL_MARK} done iptables -t mangle -A FORWARD -o ${TUNNEL_NAME} -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu iptables -t mangle -A INPUT -p esp -s ${TUNNEL_REMOTE_ENDPOINT} -d ${TUNNEL_LOCAL_ENDPOINT} -j MARK --set-xmark ${TUNNEL_MARK} ip route flush table 220 } cleanup() { IFS=',' read -ra route <<< "${TUNNEL_STATIC_ROUTE}" for i in "${route[@]}"; do ip route del ${i} dev ${TUNNEL_NAME} metric ${TUNNEL_MARK} done iptables -t mangle -D FORWARD -o ${TUNNEL_NAME} -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu iptables -t mangle -D INPUT -p esp -s ${TUNNEL_REMOTE_ENDPOINT} -d ${TUNNEL_LOCAL_ENDPOINT} -j MARK --set-xmark ${TUNNEL_MARK} ip route flush cache } delete_interface() { ip link set ${TUNNEL_NAME} down ip link del ${TUNNEL_NAME} } # main execution starts here command_exists ip || echo "ERROR: ip command is required to execute the script, check if you are running as root, mostly to do with path, /sbin/" >&2 2>&2 command_exists iptables || echo "ERROR: iptables command is required to execute the script, check if you are running as root, mostly to do with path, /sbin/" >&2 2>&2 command_exists sysctl || echo "ERROR: sysctl command is required to execute the script, check if you are running as root, mostly to do with path, /sbin/" >&2 2>&2 case "${PLUTO_VERB}" in up-client) create_interface configure_sysctl add_route ;; down-client) cleanup delete_interface ;; esac