SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-10-07

วิธีตั้งค่า WireGuard ให้เข้าถึง LAN ภายในบ้านได้จริง

ปัญหา WireGuard เชื่อมต่อสำเร็จแต่เข้าถึงอุปกรณ์ใน LAN ไม่ได้เกิดจากการตั้งค่า 4 จุดสำคัญ เรียนรู้วิธีปรับแต่ง AllowedIPs และ IP forwarding เพื่อให้แพ็กเก็ตข้อมูลรับส่งได้อย่างถูกต้อง

เหตุใด LAN ภายในบ้านของคุณจึงไม่ตอบสนองผ่าน WireGuard

การจะส่งข้อมูลไปยัง LAN ภายในบ้านผ่าน WireGuard จำเป็นต้องมีการตั้งค่า 4 ส่วนที่สอดคล้องกัน หากตั้งค่าถูกต้องเพียง 3 จาก 4 ส่วน คุณจะยังคงได้อุโมงค์เชื่อมต่อที่ดูเหมือนปกติสมบูรณ์ ซึ่งเป็นสาเหตุที่ทำให้ความผิดพลาดนี้สร้างความสับสนได้ง่าย wg show จะรายงานว่ามีการทำ handshake ล่าสุด ping 10.8.0.1 จะตอบสนองภายในเวลาไม่กี่มิลลิวินาที แต่ ping 192.168.20.10 จะไม่ส่งข้อมูลใดๆ กลับมาเลย

นี่คือรายการทั้งหมดตามลำดับที่แพ็กเก็ตข้อมูลจะผ่านไป LAN หมายถึงเครือข่ายท้องถิ่น (local area network) ซึ่งเป็นเครือข่ายส่วนตัวที่อยู่หลังเราเตอร์ในบ้านของคุณ

  1. AllowedIPs บนฝั่งไคลเอนต์ต้องครอบคลุม subnet ปลายทาง มิฉะนั้นแพ็กเก็ตจะไม่เข้าสู่อุโมงค์เชื่อมต่อ
  2. AllowedIPs บนฝั่งเซิร์ฟเวอร์ต้องครอบคลุมที่อยู่ของอุโมงค์เชื่อมต่อของไคลเอนต์ มิฉะนั้นแพ็กเก็ตจะถูกทิ้งทันทีที่ถอดรหัส
  3. net.ipv4.ip_forward บนเซิร์ฟเวอร์ต้องเป็น 1 เนื่องจาก Linux จะทิ้งแพ็กเก็ตใดก็ตามที่ไม่ได้ระบุที่อยู่ปลายทางมายังตัวเครื่องเอง
  4. LAN ต้องทราบเส้นทาง (route) ในการส่งข้อมูลกลับไปยัง 10.8.0.0/24 ผ่านกฎ masquerade บนเซิร์ฟเวอร์ หรือการตั้งค่า static route บนเราเตอร์ภายในบ้าน

ทุกข้อที่กล่าวมานี้ หากเกิดความผิดพลาดจะไม่มีข้อความแจ้งเตือนใดๆ ปรากฏขึ้น ไม่มีการบันทึก log ไม่มีการเตือน และการทำ handshake จะยังคงทำงานได้ตามปกติ ให้ตรวจสอบตามลำดับนี้แล้วคุณจะพบจุดที่ผิดพลาดภายในเวลาประมาณ 1 นาที

เครือข่ายที่ใช้ในคู่มือนี้

ที่อยู่ทุกรายการด้านล่างเป็นเพียงตัวอย่างเท่านั้น ให้แทนที่ด้วยค่าของคุณเองและรักษาความสอดคล้องในการแทนที่ เนื่องจากไฟล์คอนฟิกูเรชันที่อัปเดตไม่ครบถ้วนเป็นสาเหตุอันดับสองที่พบบ่อยที่สุดของปัญหานี้

  • เครือข่าย LAN ภายในบ้านคือ 192.168.20.0/24 โดยมีเราเตอร์ภายในบ้านคือ 192.168.20.1
  • เซิร์ฟเวอร์ WireGuard เป็นเครื่อง Linux ที่อยู่ใน LAN นั้น อินเทอร์เฟซ LAN enp1s0 มีที่อยู่เป็น 192.168.20.5 และอินเทอร์เฟซอุโมงค์ (tunnel interface) wg0 มีที่อยู่เป็น 10.8.0.1
  • โฮสต์ที่คุณต้องการเข้าถึงคือ NAS (network attached storage) ที่ 192.168.20.10
  • ไคลเอนต์คือแล็ปท็อปที่อยู่นอกสถานที่ โดยมีที่อยู่ 10.8.0.2 ภายในอุโมงค์

เซิร์ฟเวอร์เป็นเครื่องที่อยู่ใน LAN ไม่ใช่ตัวเราเตอร์เอง ซึ่งเป็นกรณีปกติ เช่น Raspberry Pi หรือมินิพีซีเครื่องเก่า สิ่งนี้มีความสำคัญสำหรับกฎข้อที่ 4: เราเตอร์ของคุณจะไม่ทราบว่ามีอุโมงค์นี้อยู่หากคุณไม่ได้กำหนดค่าบอกมัน และโฮสต์ทุกเครื่องใน LAN จะส่งทราฟฟิกที่อยู่นอกซับเน็ตไปยังเราเตอร์นั้น

หากการเชื่อมต่ออินเทอร์เน็ตที่บ้านของคุณไม่มี Public IP address วิธีการทั้งหมดนี้จะไม่สามารถใช้งานได้ด้วยตัวเอง เนื่องจากไม่มีอุปกรณ์ใดบนอินเทอร์เน็ตที่สามารถเริ่มการทำ handshake มายังบ้านของคุณได้ ส่วนที่ว่าด้วยการใช้ VPS เป็นตัวกลางจะครอบคลุมกรณีดังกล่าว โดยกฎทั้งสี่ข้อจะยังคงนำมาใช้ได้เหมือนเดิม โดยมี peer เพิ่มเข้ามาอีกหนึ่งจุดที่ต้องจัดการให้ถูกต้อง

AllowedIPs มีความหมายสองอย่างที่แตกต่างกัน

การตั้งค่าเดียวทำหน้าที่สองอย่าง และการตีความแบบเดียวกันทั้งสองฝั่งคือข้อผิดพลาดที่อยู่เบื้องหลังตั๋วปัญหาเหล่านี้ส่วนใหญ่ WireGuard เรียกกลไกนี้ว่า cryptokey routing ซึ่งอธิบายรายละเอียดไว้ใน วิธีที่ WireGuard เชื่อมโยง public key เข้ากับช่วง IP

เมื่ออ่านในฝั่งขาออก AllowedIPs คือตารางเส้นทาง (routing table) wg-quick จะเปลี่ยนแต่ละรายการให้เป็นเส้นทางที่ชี้ไปยัง wg0 แพ็กเก็ตสำหรับ 192.168.20.10 จะถูกเข้ารหัสและส่งไปยัง peer ก็ต่อเมื่อมี peer รายใดรายหนึ่งอ้างสิทธิ์ในช่วงที่ครอบคลุมที่อยู่นั้น หากระบุเพียง 10.8.0.0/24 แล็ปท็อปของคุณจะส่งทราฟฟิก LAN ออกทาง Wi-Fi ท้องถิ่นแทน ซึ่งทราฟฟิกนั้นจะสูญหายไปหรือไปถึง 192.168.20.10 ที่แตกต่างกันโดยสิ้นเชิง

เมื่ออ่านในฝั่งขาเข้า AllowedIPs คือรายการควบคุมการเข้าถึง (access control list) หลังจากที่ WireGuard ถอดรหัสแพ็กเก็ตจาก peer แล้ว มันจะตรวจสอบที่อยู่ต้นทางภายในเทียบกับ AllowedIPs ของ peer รายนั้น และจะทิ้งแพ็กเก็ตหากไม่ตรงกัน โดยจะไม่มีบรรทัด log หรือตัวนับใดๆ สำหรับการทิ้งแพ็กเก็ตนั้น แพ็กเก็ตจะหายไปเฉยๆ

ดังนั้น ไฟล์คอนฟิกทั้งสองไฟล์จึงไม่ใช่ภาพสะท้อนของกันและกัน ฝั่งไคลเอนต์จะระบุสิ่งที่ต้องการเข้าถึงผ่านเซิร์ฟเวอร์ ส่วนฝั่งเซิร์ฟเวอร์จะระบุว่าไคลเอนต์นั้นได้รับอนุญาตให้ใช้ที่อยู่ต้นทางใดได้บ้าง

คู่ไฟล์คอนฟิกที่จับคู่กัน

Client, /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32

[Peer]
PublicKey = <server public key>
Endpoint = home.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.20.0/24
PersistentKeepalive = 25

Server, /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = <server private key>
Address = 10.8.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <laptop public key>
AllowedIPs = 10.8.0.2/32

เราเตอร์ที่บ้านจำเป็นต้องทำ port forward สำหรับ UDP 51820 ไปยัง 192.168.20.5 ไม่เช่นนั้นการทำ handshake จะไม่เริ่มต้นขึ้นและ client จะบันทึก log เป็น Handshake for peer 1 did not complete after 5 seconds, retrying คู่มือนี้ถือว่าคุณได้ผ่านขั้นตอนดังกล่าวมาแล้ว

มี 4 บรรทัดที่แตกต่างจากการตั้งค่าแบบ full-tunnel ทั่วไป และแต่ละจุดมีวัตถุประสงค์ที่ชัดเจน

  • AllowedIPs = 10.8.0.0/24, 192.168.20.0/24 บนฝั่ง client แทนที่ 0.0.0.0/0, ::/0 นี่คือการทำ split tunnel: subnet ของ tunnel และ LAN ที่บ้านจะวิ่งผ่าน wg0 ส่วนทราฟฟิกอื่นทั้งหมดจะใช้เส้นทางเดิมตามปกติ การท่องเว็บของคุณจะไม่วิ่งผ่านการเชื่อมต่อที่บ้าน ซึ่งมักเป็นสิ่งที่คุณต้องการเมื่อคุณต้องการเข้าถึงเพียงแค่ NAS เท่านั้น
  • AllowedIPs = 10.8.0.2/32 บนฝั่ง server โดยระบุเป็นที่อยู่เดียวแทนที่จะเป็นช่วง หากคุณใส่ 10.8.0.0/24 ลงไป client รายนั้นอาจอ้างสิทธิ์ที่อยู่ใดก็ได้ภายใน tunnel หากคุณเพิ่ม peer รายที่สองที่มีช่วงทับซ้อนกันในภายหลัง ทราฟฟิกจะถูกส่งไปยัง peer ที่ถูกตั้งค่าล่าสุดโดยไม่มีข้อความแจ้งเตือนข้อผิดพลาดใดๆ ปรากฏขึ้น
  • PersistentKeepalive = 25 บนฝั่ง client เท่านั้น เนื่องจาก client อยู่หลัง NAT (network address translation) และเราเตอร์ของ client จะลืมการแมป UDP หลังจากไม่มีการใช้งานเพียงหนึ่งหรือสองนาที ทำให้ server ไม่สามารถติดต่อกลับมาได้ ส่วน server มี public address จึงไม่จำเป็นต้องใช้ keepalive
  • ยังไม่มีบรรทัด DNS = ในขณะนี้ การเพิ่มบรรทัดดังกล่าวจะเปลี่ยนการแก้ไขชื่อ (name resolution) สำหรับเครื่อง client ทั้งเครื่อง ส่วน DNS ด้านล่างจะอธิบายการทำงานของมันก่อนที่คุณจะเปิดใช้งาน

การทำ full tunnel สามารถเข้าถึง LAN ได้เช่นกัน เนื่องจาก 0.0.0.0/0 ครอบคลุมทุกที่อยู่ แต่มันจะทำให้คุณเสียทราฟฟิกทั้งหมดและเกิดปัญหา subnet ชนกัน ซึ่งคุณไม่สามารถแก้ไขได้จากฝั่ง client

เหตุใดการใช้ subnet เดียวกันทั้งสองฝั่งจึงทำให้ระบบใช้งานไม่ได้

ให้เลือกใช้ subnet สำหรับเครือข่ายภายในบ้านที่แทบไม่มีใครใช้ เช่น 192.168.20.0/24 หรือ 10.44.7.0/24 เนื่องจาก 192.168.1.0/24 และ 192.168.0.0/24 เป็นค่าเริ่มต้นจากโรงงานของ router สำหรับผู้ใช้งานทั่วไปส่วนใหญ่ ดังนั้นไม่ช้าก็เร็ว laptop ของคุณจะต้องไปเชื่อมต่อกับเครือข่ายในร้านกาแฟหรือโรงแรมที่ใช้ช่วง IP เดียวกันนี้อย่างแน่นอน

การชนกันของ IP เป็นปัญหาที่หยุดการทำงานของระบบโดยสิ้นเชิง และแสดงอาการต่างกันในสองกรณี หากเป็นแบบ split tunnel ตัว wg-quick จะพยายามเพิ่มเส้นทาง (route) สำหรับ prefix ที่มีอยู่แล้วบน interface Wi-Fi ทำให้ ip route add ปฏิเสธการทำงานและ interface ไม่สามารถเริ่มทำงานได้:

RTNETLINK answers: File exists

หากเป็นแบบ full tunnel ตัว wg-quick จะติดตั้งกฎ policy routing ที่จงใจกันไม่ให้เส้นทางที่เฉพาะเจาะจงกว่าเข้าไปอยู่ในตารางหลัก เส้นทาง 192.168.1.0/24 ในเครื่องจะมีความสำคัญเหนือกว่า tunnel ดังนั้นทุก packet ที่มุ่งหน้าไปยัง LAN ฝั่งปลายทางจะถูกส่งออกผ่านเครือข่ายท้องถิ่นแทน แม้ว่า tunnel จะเชื่อมต่ออยู่และ handshake สำเร็จ แต่คุณจะไม่สามารถเข้าถึง NAS ได้ การเปลี่ยนหมายเลข IP ของ LAN ที่บ้านเป็นวิธีแก้ไขปัญหาที่แท้จริงเพียงวิธีเดียว

เปลี่ยนเซิร์ฟเวอร์ให้เป็นเราเตอร์

ip route show default
printf 'net.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward

คำสั่งแรกจะแสดงชื่อจริงของอินเทอร์เฟซ LAN อิมเมจปัจจุบันใช้ชื่ออย่าง enp1s0 หรือ ens3 และไม่ค่อยพบ eth0 หากกฎ masquerade ระบุชื่ออินเทอร์เฟซผิด จะไม่สามารถจับคู่ทราฟฟิกใดๆ ได้ คำสั่งสุดท้ายควรแสดงผลลัพธ์เป็น net.ipv4.ip_forward = 1 การใช้ sudo sysctl -w เพียงอย่างเดียวจะตั้งค่าเดียวกันนี้ แต่ค่าจะหายไปหลังจากรีบูตเครื่องใหม่ ซึ่งเป็นสาเหตุคลาสสิกของรายงานปัญหาที่ว่า "มันเคยใช้งานได้จนถึงวันอังคาร"

การส่งต่อแพ็กเก็ต (forwarding) ต้องผ่านการตรวจสอบของไฟร์วอลล์ด้วย สำหรับ Ubuntu ที่เปิดใช้งาน ufw แพ็กเก็ตที่ถูกส่งต่อจะถูกปฏิเสธเว้นแต่จะตั้งค่า DEFAULT_FORWARD_POLICY="ACCEPT" ไว้ใน /etc/default/ufw ทั้งนี้ Docker จะตั้งค่านโยบายนี้ด้วยตัวเอง ดังนั้นหาก sudo iptables -S FORWARD | head -1 แสดงผลเป็น -P FORWARD DROP บนเครื่องที่คุณไม่เคยตั้งค่าไฟร์วอลล์ด้วยตนเอง แสดงว่า Docker เป็นผู้ตั้งค่าดังกล่าว และทราฟฟิกในทันเนลของคุณจำเป็นต้องมีกฎ accept ที่ชัดเจนรองรับ

เหตุใดจึงไม่ได้รับข้อมูลตอบกลับ

หากตั้งค่ากฎข้อ 1 ถึง 3 ได้ถูกต้อง แพ็กเก็ต ping จะส่งไปถึง NAS ได้จริง แต่คุณยังคงไม่เห็นผลลัพธ์ใดๆ เนื่องจากข้อมูลตอบกลับไม่มีเส้นทางกลับมายังต้นทาง NAS จะตอบกลับไปยัง 10.8.0.2 ซึ่งเป็นที่อยู่ที่อยู่นอก subnet ของตัวเอง จึงส่งแพ็กเก็ตต่อไปยัง default gateway ซึ่งก็คือเราเตอร์ที่บ้านที่ 192.168.20.1 แต่เราเตอร์ตัวนั้นไม่รู้จัก 10.8.0.0/24 จึงส่งข้อมูลตอบกลับต่อไปยัง default gateway ของมันเองซึ่งเป็นผู้ให้บริการอินเทอร์เน็ตของคุณ และถูกทิ้งไปในที่สุด คำขอจึงมาถึงแต่ข้อมูลตอบกลับถูกทำลายทิ้ง

ทางเลือก A: การทำ masquerade บนเซิร์ฟเวอร์ WireGuard เซิร์ฟเวอร์จะเขียนที่อยู่ต้นทางของทุกแพ็กเก็ตที่ส่งต่อใหม่ให้เป็น 192.168.20.5 ซึ่งเป็นที่อยู่ LAN ของตัวเซิร์ฟเวอร์เอง ทำให้ NAS มองเห็นคำขอจากอุปกรณ์ใน subnet เดียวกัน จึงตอบกลับมาที่เซิร์ฟเวอร์โดยตรง จากนั้นเซิร์ฟเวอร์จะย้อนกระบวนการเขียนที่อยู่และส่งแพ็กเก็ตกลับลงไปในอุโมงค์ (tunnel) โดยที่คุณไม่ต้องแก้ไขค่าใดๆ บนอุปกรณ์อื่นใน LAN

ให้ใส่คำสั่งนี้ไว้ในบล็อก [Interface] ของเซิร์ฟเวอร์ เพื่อให้กฎนี้ถูกสร้างและลบไปพร้อมกับการทำงานของอินเทอร์เฟซ:

PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp1s0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o enp1s0 -j MASQUERADE

สำหรับเครื่องที่จัดการด้วย nftables อยู่แล้ว ให้เขียนคำสั่งลงใน /etc/nftables.conf แทน:

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.8.0.0/24 oifname "enp1s0" counter masquerade
  }
}

ต้องคงคำสำคัญ counter เอาไว้ หากไม่มีคำนี้ sudo nft list ruleset จะแสดงผลกฎโดยไม่มีจำนวนแพ็กเก็ต ซึ่งจำนวนนี้คือสิ่งที่จะบอกคุณว่ากฎนั้นกำลังถูกใช้งานอยู่หรือไม่

การทำ masquerade ยังมีประโยชน์อีกประการที่มักถูกมองข้าม โฮสต์จำนวนมากมีไฟร์วอลล์ที่ยอมรับเฉพาะการเชื่อมต่อจาก subnet ของตัวเองเท่านั้น การแชร์ไฟล์บน Windows และแผงควบคุม NAS หลายรุ่นมีพฤติกรรมเช่นนี้โดยค่าเริ่มต้น แพ็กเก็ตที่มาจาก 10.8.0.2 จะถูกโฮสต์ปลายทางปฏิเสธแม้ว่าการตั้งค่า routing ของคุณจะสมบูรณ์แบบแล้วก็ตาม หลังจากทำ masquerade ที่อยู่ต้นทางจะกลายเป็นที่อยู่ LAN ทำให้กฎของโฮสต์เหล่านั้นยอมรับการเชื่อมต่อได้ ข้อเสียคือไคลเอนต์ในอุโมงค์ทุกคนจะปรากฏเป็น 192.168.20.5 ใน log ของทุกโฮสต์ใน LAN ทำให้คุณไม่สามารถแยกแยะไคลเอนต์แต่ละรายได้ และไม่สามารถใช้กฎที่จำกัดเฉพาะไคลเอนต์บนอุปกรณ์ใน LAN ได้

ทางเลือก B: การตั้งค่า static route บนเราเตอร์ที่บ้าน แจ้งให้เราเตอร์ทราบว่า 10.8.0.0/24 อยู่หลัง 192.168.20.5 สำหรับเราเตอร์ที่เป็น Linux สามารถทำได้ด้วยคำสั่งเดียว:

sudo ip route add 10.8.0.0/24 via 192.168.20.5

เราเตอร์ทั่วไปจะมีหน้าเมนูที่เรียกว่า Static Routes หรือ Routing อยู่ภายใต้การตั้งค่าขั้นสูง (advanced settings): ปลายทางคือ 10.8.0.0, mask คือ 255.255.255.0, gateway คือ 192.168.20.5 ให้บันทึกค่านี้ลงในการตั้งค่าของตัวเราเตอร์ เพราะคำสั่ง ip route add ที่พิมพ์บนเครื่อง Linux จะหายไปเมื่อรีบูตเครื่องใหม่

วิธีนี้จะช่วยรักษาที่อยู่จริงของไคลเอนต์ไว้ ทำให้ log และกฎที่กำหนดเฉพาะไคลเอนต์บนอุปกรณ์ใน LAN ของคุณยังคงใช้งานได้ตามปกติ วิธีนี้จำเป็นต้องใช้เราเตอร์ที่รองรับ static route และจะช่วยได้เฉพาะโฮสต์ที่ใช้เราเตอร์ตัวนั้นเป็น default gateway เท่านั้น โฮสต์ใดที่มีไฟร์วอลล์จำกัดขอบเขตเฉพาะ subnet ยังคงต้องมีกฎของตัวเองสำหรับ 10.8.0.0/24 แนะนำให้เริ่มจากวิธี masquerade เนื่องจากไม่ต้องแก้ไขค่าภายนอกเครื่องที่คุณควบคุมอยู่แล้ว และค่อยเปลี่ยนไปใช้วิธี static route เมื่อคุณต้องการทราบที่อยู่จริงของไคลเอนต์

วิธีตรวจสอบว่าจุดใดในสี่จุดที่ผิดพลาด

ให้ไล่ตรวจสอบจากฝั่ง client ออกไป แต่ละขั้นตอนจะบอกคุณว่าแพ็กเก็ตเดินทางไปถึงจุดนั้นหรือไม่

แพ็กเก็ตเข้าสู่ tunnel หรือไม่? บนเครื่อง client ให้ใช้คำสั่ง:

ip route get 192.168.20.10

คำตอบควรระบุชื่อ dev wg0 หากแสดงชื่ออินเทอร์เฟซ Wi-Fi ของคุณ แสดงว่ากฎข้อที่ 1 ผิดพลาด และ AllowedIPs ของ client ไม่ครอบคลุม subnet ของ LAN ส่วน ping: connect: Network is unreachable จะชี้ไปที่บรรทัดเดียวกัน

แพ็กเก็ตมาถึงเซิร์ฟเวอร์หรือไม่? รันคำสั่งนี้บนเซิร์ฟเวอร์ จากนั้นลอง ping ไปยัง NAS จากเครื่อง client:

sudo tcpdump -ni wg0 icmp

หากเส้นทางทำงานปกติจะแสดง IP 10.8.0.2 > 192.168.20.10: ICMP echo request โดยที่ ICMP คือ internet control message protocol ซึ่งเป็นสิ่งที่ ping ใช้งาน หากไม่พบข้อมูลใดๆ ในขณะที่การทำ handshake ปกติดี แสดงว่าเป็นไปตามกฎข้อที่ 2 คือ AllowedIPs ของเซิร์ฟเวอร์สำหรับ peer นั้นไม่ได้รวม 10.8.0.2 ไว้ แพ็กเก็ตจึงถูกทิ้งในขั้นตอนการถอดรหัสก่อนที่จะไปถึง wg0

แพ็กเก็ตถูกส่งต่อไปยัง LAN หรือไม่? บนเซิร์ฟเวอร์ ให้ตรวจสอบฝั่ง LAN:

sudo tcpdump -ni enp1s0 icmp

หากเห็นคำขอปรากฏบน wg0 แต่ไม่พบที่นี่ แสดงว่าเป็นไปตามกฎข้อที่ 3 คือการทำ forwarding ถูกปิดไว้ หรือมีกฎ FORWARD ทิ้งแพ็กเก็ตนั้น หากเห็นคำขอที่นี่โดยมี source เป็น 10.8.0.2 แต่ไม่มีการตอบกลับ แสดงว่าเป็นไปตามกฎข้อที่ 4 คือไม่มีเส้นทางส่งกลับ (route) สำหรับการตอบกลับนั้น หากเห็นคำขอที่นี่โดยมี source เป็น 192.168.20.5 แต่ไม่มีการตอบกลับ แสดงว่ากฎ masquerade ของคุณทำงานปกติ แต่โฮสต์ปลายทางปฏิเสธการเชื่อมต่อ ให้ตรวจสอบ firewall บน NAS แทน ขั้นตอนการไล่ตรวจสอบแบบเดียวกันนี้สามารถใช้กับบริการอื่นได้ เพียงแค่เปลี่ยน icmp เป็น port 445 หรือพอร์ตที่คุณต้องการตรวจสอบ

เข้าถึง IP ได้แต่เข้าถึงชื่อไม่ได้

ssh 192.168.20.10 ใช้งานได้ แต่ ssh nas.home.arpa ใช้งานไม่ได้:

ssh: Could not resolve hostname nas.home.arpa: Name or service not known

ไม่มีสิ่งใดผิดปกติกับ tunnel การแปลงชื่อเป็นเส้นทางแยกต่างหาก และแล็ปท็อปของคุณยังคงสอบถามตัวแก้ไข (resolver) ที่ได้รับมาจาก Wi-Fi ในพื้นที่ ตัวแก้ไขนั้นไม่รู้จักชื่อต่างๆ บนเครือข่ายที่บ้านของคุณ

เงื่อนไขสองประการต้องเป็นจริงเพื่อให้ชื่อในเครือข่ายที่บ้านใช้งานได้ ประการแรก ที่อยู่ของตัวแก้ไขต้องอยู่ภายใน AllowedIPs บนฝั่งไคลเอนต์ ไม่เช่นนั้นคำขอ DNS (domain name system) จะไม่เข้าสู่ tunnel ประการที่สอง ตัวแก้ไขต้องยินยอมตอบคำถามที่มีที่อยู่ต้นทางเป็น 10.8.0.2 ตัวแก้ไขในบ้านหลายตัวปฏิเสธการทำงานนี้โดยค่าเริ่มต้น: dnsmasq ที่ทำงานด้วย local-service จะตอบเฉพาะคำถามจาก subnet ที่เชื่อมต่อโดยตรงเท่านั้น และ Pi-hole มีโหมดการฟังที่อนุญาตเฉพาะคำขอจากภายในพื้นที่เท่านั้น กฎ masquerade จะช่วยปกปิดปัญหานี้ เนื่องจากหลังจากเขียนที่อยู่ใหม่แล้ว คำขอจะดูเหมือนมาจาก 192.168.20.5

ฝั่งไคลเอนต์ใช้เพียงบรรทัดเดียว:

DNS = 192.168.20.1

บนไคลเอนต์ Linux ที่ต้องการ openresolv หรือสิ่งที่เทียบเท่ากัน ไม่เช่นนั้น wg-quick จะหยุดทำงานพร้อมกับ resolvconf: command not found โปรดทำความเข้าใจการทำงานของมันบนเครื่องที่ใช้ systemd-resolved ก่อนตั้งค่า: wg-quick จะลงทะเบียนเซิร์ฟเวอร์เหล่านั้นแบบผูกขาด ดังนั้นในขณะที่ tunnel เชื่อมต่ออยู่ การค้นหาทุกอย่างบนแล็ปท็อปจะไปที่ตัวแก้ไขที่บ้านของคุณ ไม่ใช่แค่ชื่อในเครือข่ายที่บ้านเท่านั้น ตรวจสอบผลลัพธ์ด้วย resolvectl status wg0 หากคุณต้องการให้ชื่อในเครือข่ายที่บ้านถูกแปลงที่บ้านและชื่ออื่นๆ ถูกแปลงในพื้นที่ นั่นคือ split DNS ซึ่ง การแก้ไข DNS ผ่าน WireGuard tunnel ได้ครอบคลุมการตั้งค่าไว้อย่างครบถ้วนแล้ว

ไม่มี Public IP ที่บ้าน? ใช้ VPS เป็นตัวกลาง

หากหน้าสถานะของ Router แสดง WAN address ที่อยู่ในช่วง 100.64.0.0/10 หรือเป็น private address ในช่วง 192.168.x.x แสดงว่าคุณอยู่หลัง CGNAT (carrier grade network address translation) ทำให้การเชื่อมต่อจากอินเทอร์เน็ตภายนอกไม่สามารถเข้าถึงบ้านคุณได้โดยตรง แต่การเชื่อมต่อขาออกยังคงทำงานได้ตามปกติ วิธีแก้ไขคือการใช้โหนดที่สามที่มี public address โดยให้ VPS ขนาดเล็กทำหน้าที่เป็นฮับ และเครื่องที่บ้านเชื่อมต่อออกไปยัง VPS นั้น

กฎ 4 ข้อไม่มีการเปลี่ยนแปลง แต่เนื่องจากต้องผ่าน 2 ฮอป การจัดการข้อมูลจึงเพิ่มขึ้นเป็นสองเท่า

  • บน VPS ในส่วน peer entry ของเครื่องที่บ้าน ให้ใส่ AllowedIPs = 10.8.0.3/32, 192.168.20.0/24 ซึ่งประกอบด้วย tunnel address ของเครื่องนั้น และ subnet ที่อนุญาตให้สื่อสารได้
  • บน VPS ในส่วน peer entry ของแล็ปท็อป ให้คงค่าเป็น AllowedIPs = 10.8.0.2/32
  • บนแล็ปท็อป ในส่วน peer ของ VPS ให้ใส่ AllowedIPs = 10.8.0.0/24, 192.168.20.0/24 เพราะทุกอย่างต้องวิ่งผ่านฮับ
  • บนเครื่องที่บ้าน ในส่วน peer ของ VPS ให้ใส่ AllowedIPs = 10.8.0.0/24 และเครื่องที่บ้านต้องตั้งค่า PersistentKeepalive = 25 เนื่องจากเป็นฝั่งที่อยู่หลัง NAT
  • VPS จำเป็นต้องเปิด net.ipv4.ip_forward = 1 ด้วย และ forward chain ของ firewall ต้องอนุญาตให้ wg0 ส่งต่อไปยัง wg0 เพราะทราฟฟิกของแล็ปท็อปจะเข้ามาและออกไปผ่านอินเทอร์เฟซเดียวกัน หาก firewall ถูกเขียนมาสำหรับ VPS แบบ full-tunnel ทั่วไป มันจะบล็อกการทำงานนี้โดยอัตโนมัติ

หากคุณยังไม่ได้ตั้งค่าฝั่ง VPS สามารถดู การตั้งค่า WireGuard บน VPS ซึ่งครอบคลุมการสร้างคีย์, การตั้งค่า firewall และ systemd unit ส่วนรูปแบบการเข้าถึงเครื่องที่ไม่สามารถรับการเชื่อมต่อขาเข้าได้นั้นอยู่ใน การเปิด reverse tunnel จากหลัง CGNAT และเมื่อการจัดการ peer address ด้วยตนเองเริ่มยุ่งยาก คุณสามารถใช้ การรัน Tailscale subnet router เพื่อทำงาน routing เดียวกันโดยมีระบบจัดการ address อัตโนมัติ

ทำให้ทำงานได้ต่อเนื่องหลังรีบูต

sudo systemctl enable --now wg-quick@wg0
sudo systemctl enable --now nftables
sudo wg show

enable --now คือขั้นตอนที่คนส่วนใหญ่มักข้ามไป การรัน wg-quick up wg0 ด้วยมือจะหายไปหลังจากมีการอัปเกรดเคอร์เนลและรีบูตเครื่องครั้งถัดไป wg show ควรแสดงรายการ peer พร้อมบรรทัด latest handshake ล่าสุดและตัวนับการรับส่งข้อมูลที่ไม่เป็นศูนย์ในทั้งสองทิศทาง

การเพิ่มไคลเอนต์ตัวที่สองในภายหลังไม่จำเป็นต้องรีสตาร์ท ซึ่งจะทำให้ทุกคนที่เชื่อมต่ออยู่หลุดจากการเชื่อมต่อ:

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

wg-quick strip จะแสดงการตั้งค่าโดยไม่มีคีย์ที่เฉพาะ wg-quick เท่านั้นที่เข้าใจ และ syncconf จะนำส่วนต่างไปปรับใช้ในขณะที่เซสชันปัจจุบันยังคงทำงานอยู่ โดยจะอัปเดตเฉพาะ peer เท่านั้น หากมีการเปลี่ยนแปลง Address หรือเพิ่มบรรทัด PostUp ใหม่ ยังคงจำเป็นต้องสั่ง down และ up ทั้งระบบใหม่ทั้งหมด

FAQ

ทำไมฉันถึง ping ไปยังเซิร์ฟเวอร์ WireGuard ได้ แต่ไม่สามารถเข้าถึงอุปกรณ์อื่นใน LAN ที่บ้านได้?

การ ping ไปยัง 10.8.0.1 เป็นเพียงการพิสูจน์ว่าอุโมงค์เชื่อมต่ออยู่เท่านั้น การเข้าถึงส่วนอื่นของ LAN เป็นปัญหาเรื่องการกำหนดเส้นทาง (routing) ค่า AllowedIPs ของไคลเอนต์ต้องระบุ 192.168.20.0/24 ไว้ด้วย มิฉะนั้นแพ็กเก็ตจะไม่เข้าสู่อุโมงค์ เซิร์ฟเวอร์จำเป็นต้องตั้งค่า net.ipv4.ip_forward เป็น 1 ไม่เช่นนั้นเซิร์ฟเวอร์จะทิ้งแพ็กเก็ตที่ไม่ได้ส่งถึงตัวมันเอง และเครือข่าย LAN จำเป็นต้องมีเส้นทางกลับไปยัง 10.8.0.0/24 ให้รันคำสั่ง sudo tcpdump -ni enp1s0 icmp บนเซิร์ฟเวอร์ในขณะที่คุณ ping หากคำขอออกจากเซิร์ฟเวอร์ด้วย source 10.8.0.2 แต่ไม่มีการตอบกลับ แสดงว่าปัญหาอยู่ที่เส้นทางขากลับ

ฉันจำเป็นต้องตั้งค่า static route บนเราเตอร์ที่บ้านหรือไม่?

จำเป็นเฉพาะในกรณีที่คุณไม่ใช้กฎ masquerade กฎ masquerade บนเซิร์ฟเวอร์ WireGuard จะเขียนที่อยู่ต้นทางของทราฟฟิกในอุโมงค์ใหม่ให้เป็นที่อยู่ LAN ของเซิร์ฟเวอร์เอง ทำให้อุปกรณ์ใน LAN ตอบกลับไปยังโฮสต์ที่รู้จักอยู่แล้วโดยไม่ต้องผ่านเราเตอร์ การตั้งค่า static route สำหรับ 10.8.0.0/24 ผ่านที่อยู่ LAN ของเซิร์ฟเวอร์เป็นอีกทางเลือกหนึ่ง ซึ่งคุ้มค่าหากคุณต้องการเห็นที่อยู่จริงของไคลเอนต์ใน log ของอุปกรณ์ LAN หรือต้องการตั้งกฎ firewall แยกตามไคลเอนต์

ทำไม subnet เดียวกันที่ปลายทางทั้งสองฝั่งถึงทำให้อุโมงค์ใช้งานไม่ได้?

แล็ปท็อปของคุณไม่สามารถเก็บเส้นทางสองเส้นทางสำหรับ prefix เดียวกันได้ หากเครือข่ายท้องถิ่นแจกจ่าย 192.168.1.0/24 และ LAN ที่บ้านของคุณก็เป็น 192.168.1.0/24 เช่นกัน การทำ split-tunnel wg-quick up จะล้มเหลวเมื่อ ip route add ปฏิเสธด้วย RTNETLINK answers: File exists ในทางกลับกัน full tunnel อาจจะเชื่อมต่อได้ แต่ wg-quick จะติดตั้งกฎ policy ที่ทำให้เส้นทางที่เฉพาะเจาะจงกว่าถูกเก็บไว้ในตารางหลัก ส่งผลให้เครือข่ายท้องถิ่นชนะและไม่สามารถเข้าถึง LAN ระยะไกลได้ วิธีแก้ไขคือเปลี่ยนหมายเลข LAN ที่บ้านให้เป็นช่วงที่หายาก เช่น 192.168.20.0/24 โดยไม่มีวิธีแก้ไขที่ฝั่งไคลเอนต์

ฉันเข้าถึง NAS ผ่าน IP ได้ แต่เข้าถึงผ่านชื่อไม่ได้ เกิดจากอะไร?

การแปลงชื่อ (name resolution) ไม่ได้วิ่งผ่านอุโมงค์โดยอัตโนมัติ ให้เพิ่ม DNS = 192.168.20.1 ซึ่งเป็นตัวแปลงชื่อที่บ้านของคุณ ลงในบล็อก [Interface] ของไคลเอนต์ และตรวจสอบให้แน่ใจว่าที่อยู่นั้นอยู่ใน AllowedIPs ของ peer ไม่เช่นนั้นคำถามจะไม่เข้าสู่อุโมงค์ จากนั้นตรวจสอบว่าตัวแปลงชื่อตอบสนองต่อคำถามจากนอก subnet ของตัวเองหรือไม่ เพราะ dnsmasq ที่มี local-service และโหมดการฟังแบบ local-only ของ Pi-hole จะปฏิเสธคำถามเหล่านี้ กฎ masquerade บนเซิร์ฟเวอร์ WireGuard สามารถแก้ปัญหานี้ได้โดยการเขียนที่อยู่ต้นทางของคำถามใหม่

การเชื่อมต่อที่บ้านไม่มี public IP ฉันยังสามารถเข้าถึง LAN ได้หรือไม่?

ได้ โดยใช้โหนดที่สาม หากอยู่หลัง CGNAT ที่อยู่ WAN ของเราเตอร์จะเป็นที่อยู่ส่วนตัว ทำให้ peer อื่นบนอินเทอร์เน็ตไม่สามารถเริ่มการจับมือ (handshake) กับเราเตอร์ได้ ในขณะที่การเริ่มจับมือจากภายในออกไปภายนอกยังคงทำงานได้ตามปกติ ให้รัน WireGuard บน VPS ที่มี public IP แล้วให้เครื่องที่บ้านเชื่อมต่อออกไปยัง VPS ด้วย PersistentKeepalive = 25 จากนั้นกำหนดค่า peer ของเครื่องที่บ้านบน VPS ให้มี AllowedIPs ที่ระบุที่อยู่อุโมงค์ของเครื่องที่บ้านบวกกับ 192.168.20.0/24 จากนั้น VPS จำเป็นต้องเปิดใช้งานการส่งต่อ (forwarding) และตั้งกฎ forward ที่อนุญาตให้ wg0 ไปยัง wg0 ได้