ฉันมีเซิร์ฟเวอร์ wireguard ทำงานที่บ้านเพื่อให้สามารถเข้าสู่เครือข่ายในบ้านของฉันจากภายนอกได้ Wireguard กำลังใช้ UDP น่าเสียดายที่ฉันไม่สามารถเปิดพอร์ต IPv4 UDP ในกล่อง fritz ของฉันเหมือนที่เคยใช้งานได้ในสมัยก่อน เพราะผู้ให้บริการของฉันอยู่เบื้องหลัง CG-NAT ฉันต้องใช้ IPv6 แต่ IPv6 ยังไม่สามารถใช้งานได้ในที่ทำงานของฉัน
ดังนั้นที่บ้านฉันมี IPv6 และที่ทำงานฉันมี IPv4 และไม่มีทางที่จะเข้าถึงเครือข่ายในบ้านของฉันได้
ฉันยังมี VPS ที่มี IPv4 สาธารณะซึ่งฉันสามารถสร้างอุโมงค์ ssh แบบย้อนกลับสำหรับการรับส่งข้อมูล TCP ได้ น่าเสียดายที่อุโมงค์ ssh รองรับเฉพาะ TCP และไม่ควรทำการเชื่อมต่อ VPN ผ่าน TCP อยู่ดี ซึ่งเป็นสาเหตุที่ wireguard ใช้เพียง UDP เท่านั้น
VPN-Server VPN-Client
(UDP) | | (IPv4 UDP)
| | | not possible |
-----------|--------| <-------------------
| |
NAT CG-NAT
VPN-Server VPN-Client
(UDP) (IPv4 UDP)
| |
| |
inside agent outside agent
tunnel tunnel
|| | | ||
|| punch| punch| ||
| --------->|-------->|-------------------- |
-----------|<--------|<--------------------
| |
| |
NAT CG-NAT
ตัวแทนภายนอกกำลังทำงานบน VPS ที่มี IPv4 สาธารณะ
เอเจนต์ภายในจะส่งดาตาแกรม UDP ไปยัง IP สาธารณะและพอร์ตของเอเจนต์ภายนอก ซึ่งจะเจาะเข้าไปใน NAT ทั้งสอง เอเจนต์ภายนอกจะได้รับดาตาแกรมเหล่านี้และเรียนรู้จากที่อยู่ต้นทางและพอร์ตวิธีการส่งดาตาแกรมกลับไปยังเอเจนต์ภายใน .
ไคลเอนต์ VPN สามารถส่ง UDP ไปยังตัวแทนภายนอก และดาตาแกรมเหล่านี้จะถูกส่งต่อไปยังตัวแทนภายใน และจากที่นั่นไปยังเซิร์ฟเวอร์ VPN เซิร์ฟเวอร์ VPN สามารถตอบกลับไปยังตัวแทนภายใน สิ่งเหล่านี้จะถูกส่งต่อไปยังตัวแทนภายนอก และจากที่นั่นไปยัง ไคลเอนต์ VPN
ตัวแทนภายนอกจะปรากฏเป็นเซิร์ฟเวอร์ VPN ไปยังไคลเอนต์ และตัวแทนภายในจะปรากฏเป็นไคลเอนต์ VPN ไปยังเซิร์ฟเวอร์
การเชื่อมต่อไคลเอ็นต์หลายรายการเป็นไปได้เนื่องจากจะใช้ช่องสัญญาณและซ็อกเก็ตใหม่บนเอเจนต์ภายในสำหรับไคลเอ็นต์ใหม่ทุกตัวที่เชื่อมต่อจากภายนอก ดังนั้นไปยังเซิร์ฟเวอร์ จะปรากฏเหมือนกับว่าไคลเอนต์หลายตัวกำลังทำงานบนโฮสต์ของตัวแทนภายใน
โคลนหรือแตกโค้ดบนทั้งสองเครื่องแล้วสร้างมันขึ้นมา คุณต้องมี make และ gcc เป็นอย่างน้อย ป้อนไดเร็กทอรีต้นทางและใช้คำสั่ง
$ make
หลังจากสร้างสำเร็จ คุณจะพบกับไบนารี udp-tunnel
ในโฟลเดอร์เดียวกัน ตอนนี้คุณสามารถเริ่มต้นได้โดยตรงจากเทอร์มินัล (แน่นอนว่ามีตัวเลือกที่ถูกต้อง) เพื่อทำการทดสอบอย่างรวดเร็วหรือจะติดตั้งโดยใช้ makefile ก็ได้
udp-tunnel
ไบนารีที่คอมไพล์แล้วสามารถทำหน้าที่เป็นเอเจนต์ภายในหรือเอเจนต์ภายนอกได้ ขึ้นอยู่กับตัวเลือกที่คุณส่งผ่านบรรทัดคำสั่ง
สมมติว่าเป็นตัวอย่างที่เซิร์ฟเวอร์ VPN กำลังฟังบน UDP 1234 ทำงานบน localhost (เหมือนกับตัวแทนภายใน) และเครื่องภายนอกคือ jump.example.com และเราต้องการให้ฟังบนพอร์ต UDP 9999
ที่โฮสต์ด้านในเราเริ่มต้นด้วย
$ ./udp-tunnel -s localhost:1234 -o jump.example.com:9999
โฮสต์ภายนอกเราเริ่มต้นด้วย
$ ./udp-tunnel -l 9999
makefile มีเป้าหมายการติดตั้ง 3 รายการ: install
เพื่อติดตั้งเฉพาะไบนารี install-outside
และ install-inside
เพื่อติดตั้งไฟล์บริการ systemd สองตัวหลังต้องการตัวแปรที่ส่งผ่านเพื่อให้ทำงานได้อย่างถูกต้อง
ในการติดตั้งเอเจนต์ภายนอกบนจัมเปอร์โฮสต์ (สมมติว่าคุณต้องการพอร์ต 9999) คุณดำเนินการคำสั่งนี้:
$ sudo make install-outside listen=9999
สิ่งนี้จะติดตั้งไบนารีลงใน /usr/local/bin/
และติดตั้งไฟล์บริการ systemd ลงใน /etc/systemd/system/
ซึ่งมีคำสั่งที่จำเป็นเพื่อเริ่มในโหมดเอเจนต์ภายนอกด้วยพอร์ต 9999
หากต้องการติดตั้ง Inside Agent บนเครื่องภายใน ให้ใช้คำสั่งต่อไปนี้ (สมมติว่าเซิร์ฟเวอร์ VPN ของคุณคือ localhost:1234 และโฮสต์ Jump ของคุณคือ Jump.example.com ตามตัวอย่าง):
$ sudo make install-inside service=localhost:1234 outside=jump.example.com:9999
สิ่งนี้จะติดตั้งไบนารีอีกครั้งใน /usr/local/bin/
และไฟล์หน่วย systemd ลงใน /etc/systemd/system/
ณ จุดนี้คุณอาจต้องการดูไฟล์ systemd unit อย่างรวดเร็วเพื่อดูว่ามีการใช้ไบนารี่อย่างไรและตรวจสอบว่าตัวเลือกนั้นถูกต้องหรือไม่ ตัวเลือกควรมีลักษณะตามที่อธิบายไว้ข้างต้นในการทดสอบด่วน
หลังจากที่ไฟล์ systemd ได้รับการติดตั้งและยืนยันว่าถูกต้อง ไฟล์เหล่านั้นยังไม่ได้เปิดใช้งานสำหรับการเริ่มอัตโนมัติ คุณจะต้องเปิดใช้งานและเริ่มต้นไฟล์เหล่านั้น บนเครื่องด้านใน:
$ sudo systemctl enable udp-tunnel-inside.service
$ sudo systemctl start udp-tunnel-inside.service
และบนเครื่องด้านนอก
$ sudo systemctl enable udp-tunnel-outside.service
$ sudo systemctl start udp-tunnel-outside.service
ไม่มีการเข้ารหัส แพ็กเก็ตจะถูกส่งต่อเหมือนเดิม โดยถือว่าบริการใดก็ตามที่คุณกำลังเจาะช่องสัญญาณจะรู้วิธีป้องกันหรือเข้ารหัสข้อมูลด้วยตัวมันเอง โดยปกติจะเป็นกรณีนี้สำหรับการเชื่อมต่อ VPN
นอกจากนี้ ผู้โจมตีอาจต้องการปลอมแปลงแพ็กเก็ต Keepalive จากตัวแทนภายในเพื่อสร้างความสับสนให้กับตัวแทนภายนอก และเปลี่ยนเส้นทางอุโมงค์ไปยังเครื่องของเขาเอง ส่งผลให้บริการหยุดชะงัก เพื่อป้องกันการโจมตีแบบง่ายๆ นี้ ดาตาแกรม Keepalive สามารถตรวจสอบความถูกต้องด้วยรหัสการตรวจสอบข้อความแบบแฮช คุณสามารถใช้รหัสผ่านที่แชร์ล่วงหน้าได้โดยใช้ตัวเลือก -k บนปลายช่องสัญญาณทั้งสองเพื่อเปิดใช้งานคุณสมบัตินี้
ในโฮสต์ภายในคุณจะใช้มันเช่นนี้
$ ./udp-tunnel -s localhost:1234 -o jump.example.com:9999 -k mysecretpassword
ภายนอกโฮสต์ คุณจะเริ่มด้วย
$ ./udp-tunnel -l 9999 -k mysecretpassword
หลังจากที่คุณได้ขั้นตอนการติดตั้งจากด้านบนทำงานได้สำเร็จ คุณอาจต้องการแก้ไขไฟล์ systemd ของคุณทั้งสองด้านด้วยตนเองและเพิ่มตัวเลือก -k จากนั้นโหลดซ้ำและรีสตาร์ททั้งสองด้าน
ข้อความ Keepalive จะมี SHA-256 บนรหัสผ่านนี้และ Nonce ที่เพิ่มขึ้นอย่างเคร่งครัด ซึ่งสามารถใช้ได้เพียงครั้งเดียวเท่านั้นเพื่อป้องกันการโจมตีเล่นซ้ำแบบธรรมดา
เอเจนต์ทั้งสองรักษารายการการเชื่อมต่อ แต่ละการเชื่อมต่อจะเก็บที่อยู่ซ็อกเก็ตและหมายเลขอ้างอิงซ็อกเก็ตที่เกี่ยวข้องกับการเชื่อมต่อไคลเอนต์นั้น ๆ
เมื่อเริ่มต้นเอเจนต์ภายในจะเริ่มอุโมงค์ขาออกไปยังเอเจนต์ภายนอก ทำเครื่องหมายว่าไม่ได้ใช้ และส่งแพ็กเก็ต Keepalive ไปบนนั้น ตัวแทนภายนอกจะเห็นแพ็กเก็ตเหล่านี้และเพิ่มช่องสัญญาณนี้พร้อมที่อยู่ต้นทางไปยังรายการการเชื่อมต่อของตนเอง แพ็กเก็ต Keepalive ได้รับการลงนามด้วย nonce และรหัสการตรวจสอบสิทธิ์ ดังนั้นจึงไม่สามารถปลอมแปลงหรือเล่นซ้ำได้
เมื่อไคลเอนต์เชื่อมต่อ เจ้าหน้าที่ภายนอกจะส่งข้อมูลไคลเอนต์ลงไปที่อุโมงค์สำรองที่ไม่ได้ใช้ เจ้าหน้าที่ภายในจะเห็นสิ่งนี้ ทำเครื่องหมายอุโมงค์ว่าใช้งานอยู่ สร้างซ็อกเก็ตสำหรับการสื่อสารกับบริการ และส่งต่อข้อมูลในทั้งสองทิศทาง จากนั้นจะสร้างอุโมงค์สำรองขาออกใหม่ทันทีเพื่อเตรียมพร้อมสำหรับลูกค้าที่เข้ามารายถัดไป
เมื่ออุโมงค์สำรองใหม่มาถึงตัวแทนภายนอก อุโมงค์สำรองจะเพิ่มเข้าไปในรายการการเชื่อมต่อของตัวเองเพื่อให้สามารถให้บริการไคลเอนต์ที่เชื่อมต่อถัดไปได้ทันที
ณ จุดนี้ เอเจนต์ทั้งสองมี 2 ทันเนลในรายการ โดยอันหนึ่งใช้งานอยู่และอีกอันว่าง กำลังรอการเชื่อมต่อไคลเอนต์ครั้งถัดไป
การหมดเวลาของการไม่ใช้งานจะทำให้แน่ใจว่าอุโมงค์ที่ไม่ทำงาน (ที่ถูกทำเครื่องหมายว่าใช้งานอยู่ในอดีต แต่ไม่มีข้อมูลไคลเอนต์มาระยะหนึ่งแล้ว) จะถูกลบออก และซ็อกเก็ตจะถูกปิด ตัวแทนภายในจะตรวจจับการขาดข้อมูลที่ส่งต่อเป็นเวลานาน ลบออกจากรายการของตัวเองและปิดซ็อกเก็ต จากนั้นในเวลาต่อมาตัวแทนภายนอกจะตรวจพบว่าไม่มี Keepalive มาถึงอีกต่อไปสำหรับการเชื่อมต่อนี้ และลบออกจากตัวมันเอง รายการด้วย
โค้ดนี้ยังคงอยู่ในช่วงทดลอง ดังนั้นอย่าสร้างธุรกิจมูลค่าหลายล้านดอลลาร์จากโค้ดนี้ อย่างน้อยก็ในตอนนี้ มันตอบสนองความต้องการได้อย่างสมบูรณ์แบบสำหรับฉัน แต่มันอาจจะพังและไหม้และระเบิดเซิร์ฟเวอร์ของคุณเพื่อคุณ คุณได้รับคำเตือน