เซิร์ฟเวอร์ Wireguard และไคลเอนต์สามารถ ping กันได้ แต่ไคลเอนต์ Wireguard ไม่สามารถ Ping กันได้
ฉันกำลังตั้งค่าการกำหนดค่า Wireguard โดยที่ฉันมีเอนทิตีต่อไปนี้:
อินสแตนซ์ VM ระยะไกลบนโฮสต์เช่น google cloud หรือ amazon aws นี่คือไคลเอนต์ระยะไกลไปยังเซิร์ฟเวอร์ Wireguard ของฉัน ลองเรียกสิ่งนี้
gcp_client
เซิร์ฟเวอร์ Wireguard บนเครื่องที่โฮสต์บน LAN ของฉัน เรียกสิ่งนี้
srvlan
ว่า
- ส่งต่อ IPv4
sysctl
ถูกเปิดใช้งานบนอุปกรณ์นี้โดย - มี Ubiquiti Edgerouter 4 ระหว่าง WAN และ LAN ของฉัน ฉันเปิดใช้งานการส่งต่อพอร์ตและปักหมุด NAT บนอุปกรณ์นี้แล้ว ฉันได้ตั้งค่าไดนามิก DNS บนเราเตอร์นี้แล้ว
- ไคลเอนต์อย่างน้อยหนึ่งเครื่องบน LAN ของฉันซึ่งควรจะสามารถเชื่อมต่อกับไคลเอนต์ระยะไกลราวกับว่าเป็นเครื่องบน LAN ของฉัน
client1
ขณะที่ผมกำลังเผชิญปัญหากับลูกค้าครั้งแรกของฉันเองขอเรียกว่า
ในการตั้งค่าของฉันฉันสามารถ ping ระหว่างsrvlan
และgcp_client
ทั้งสองทางและระหว่างclient1
และsrvlan
ด้วย อย่างไรก็ตาม pings จากgcp_client
ถึงclient1
(และในทางกลับกัน) ล้มเหลว
จากการอ่านผลลัพธ์ของtcpdump -i wg0 -n icmp
ฉันได้ทำการสังเกตดังต่อไปนี้:
- ส่ง Ping จาก
client1
ไปgcp_client
ถึงsrvlan
แต่จะไม่ส่งต่อไปยังเราเตอร์ - ปิงจาก
gcp_client
การเข้าถึงเราเตอร์ของฉันซึ่งส่งต่อไปยังclient1
srvlan
แต่แพ็คเก็ตไม่ได้รับการส่งต่อโดยการsrvlan
client1
สิ่งเดียวที่ฉันสามารถสรุปได้ก็คือกฎการส่งต่อsrvlan
นั้นผิดพลาดอย่างใด ฉันกำลังใช้nftables
เพื่อจัดการอุปกรณ์นี้
นี่คือการกำหนดค่า wireguard ของฉัน มีการเปลี่ยนแปลงที่อยู่ IP และหมายเลขพอร์ต
# wg0.conf for gcp_client
[Interface]
Address = 10.0.1.2/24
ListenPort = 50000
PrivateKey = gcp_client_privkey
[Peer]
PublicKey = srvlan_pubkey
AllowedIPs = 10.0.1.0/24
Endpoint = srvlan_ddns:50000
# wg0.conf for srvlan
[Interface]
Address = 10.0.1.1/24
ListenPort = 50000
PrivateKey = srvlan_privkey
[Peer]
PublicKey = gcp_client_pubkey
AllowedIPs = 10.0.1.2/32
Endpoint = gcp_client_domainname:50000
PersistentKeepalive = 25
[Peer]
PublicKey = client1_pubkey
AllowedIPs = 10.0.1.3/32
Endpoint = client1_lanhostname:50000
PersistentKeepalive = 25 # I realise this one is unnecessary, but I had added it while testing just in case the problem got fixed.
# wg0.conf for client1
[Interface]
Address = 10.0.1.3/24
ListenPort = 50000
PrivateKey = client1_privkey
[Peer]
PublicKey = srvlan_pubkey
AllowedIPs = 10.0.1.0/24
Endpoint = srvlan_lanhostname:50000
srvlan
นี่คือไฟร์วอลล์ของฉันใน
# nft list ruleset
table inet firewall {
chain inbound {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif "lo" accept
ip protocol icmp accept
ip6 nexthdr ipv6-icmp accept
ip protocol igmp accept
tcp dport 22 accept
iifname "eno1" tcp dport { 80, 443 } ct state new accept
iifname "eno1" udp dport 50000 ct state new accept
iifname "wg0" udp dport 53 ct state new accept
iifname "wg0" tcp dport { 80, 443 } ct state new accept
iifname "wg0" udp dport 50000 ct state new accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iifname "wg0" oifname "eno1" ct state new accept
}
chain outbound {
type filter hook output priority filter; policy accept;
ct state invalid drop
}
}
table ip router {
chain prerouting {
type nat hook prerouting priority filter; policy accept;
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "eno1" ip saddr 10.0.1.0/24 masquerade
}
}
คำตอบ
เมื่อsrvlanส่งต่อการรับส่งข้อมูล WireGuard-tunneled จะได้รับจากwg0และกำหนดเส้นทางไปยัง ... wg0อีกครั้ง: สองครั้งของอินเทอร์เฟซเดียวกัน
ดังนั้นคุณต้องต่อท้ายรายการนี้เข้ากับห่วงโซ่การส่งต่อของnftables ไฟร์วอลล์ inet :
iifname "wg0" oifname "wg0" accept
ปัญหาอื่น ๆ ในห่วงโซ่ขาเข้า :
ip protocol icmp accept ip6 nexthdr ipv6-icmp accept ip protocol igmp accept
แม้ว่าโปรโตคอลจะทำงานสำหรับ IPv4 แต่nexthdrในโปรโตคอล IPv6 ไม่รับประกันว่า Next Header จะเป็น ICMPv6: อาจมีส่วนขยายหลายส่วนระหว่างส่วนหัวคงที่และส่วนหัวของโปรโตคอลชั้นบน หากส่วนหัวของส่วนขยายดังกล่าวปรากฏในบางแพ็กเก็ตก็nexthdr ipv6-icmp
จะไม่ตรงกันอีกต่อไป ใช้ไวยากรณ์ที่ถูกต้องสำหรับ IPv4 และ IPv6:
meta nfproto ipv4 meta l4proto icmp accept
meta nfproto ipv6 meta l4proto ipv6-icmp accept
meta nfproto ipv4 meta l4proto igmp accept
ขึ้นอยู่กับเวอร์ชันnftablesซึ่งจะแสดงกลับมาในรูปแบบที่ง่ายขึ้น
iifname "wg0" udp dport 50000 ct state new accept
พอร์ต 50000 ไม่ปรากฏภายในอินเทอร์เฟซ WireGuard (เว้นแต่คุณต้องการอุโมงค์ WireGuard ภายใน WireGuard) แต่อยู่ภายนอก (ซึ่งมีกฎอยู่แล้ว) มันไม่ควรจำเป็น
โปรดจำไว้ว่าเมื่อคุณเพิ่มลูกค้า WireGuard เพิ่มเติม / เพื่อนร่วมงาน (ตามที่คุณได้อย่างถูกต้อง) ที่ไม่สามารถมีการทับซ้อนในsrvlan 's AllowedIPsรายการตั้งแต่พวกเขาตรวจสอบ cryptorouting ที่เกิดขึ้นใน WireGuard เพื่อเลือกเพียร์ที่เพียงพอหลังจากเส้นทางมาตรฐาน นอกจากนี้ถ้าgcp_clientเชื่อมต่อผ่านsrvlanไปยังเซิร์ฟเวอร์ไม่ได้ใช้อุโมงค์ WireGuard แล้ว LAN ที่อยู่ของพวกเขายังต้องได้รับการเพิ่มทั้งกับAllowedIPsและตารางกำหนดเส้นทางของgcp_client AllowedIPsถูกใช้เพื่อรับแพ็กเก็ตตามแหล่งที่มา (และกำหนดเพียร์และอาจอัปเดตจุดสิ้นสุดในกรณีโรมมิ่ง) และกำหนดเพียร์ที่จะส่งแพ็กเก็ตตามปลายทาง