SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor

วิธีตั้งค่า Tailscale subnet router บน VPS อย่างถูกต้อง

เรียนรู้วิธีตั้งค่า Tailscale subnet router บน VPS เพื่อเข้าถึงเครือข่ายส่วนตัว ครอบคลุมการเปิดใช้งาน IP forwarding การตั้งค่า --accept-routes และการอนุมัติเส้นทางให้ใช้งานได้ถาวร

หน้าที่ของ Tailscale subnet router

Tailscale subnet router คือเครื่องคอมพิวเตอร์หนึ่งเครื่องที่ทำหน้าที่ประกาศช่วง IP address ส่วนตัวทั้งหมดให้แก่ tailnet ของคุณ เพื่อให้อุปกรณ์ทุกเครื่องใน tailnet สามารถเข้าถึง IP address ในช่วงดังกล่าวได้ แม้ว่าอุปกรณ์เหล่านั้นจะไม่ได้ติดตั้ง Tailscale ไว้ก็ตาม tailnet คือเครือข่าย Tailscale ส่วนตัวของคุณ ซึ่งประกอบด้วยกลุ่มอุปกรณ์ที่ลงชื่อเข้าใช้ด้วยบัญชีหรือองค์กรเดียวกัน ส่วน exit node เป็นฟีเจอร์ที่มักถูกสับสนกับ subnet router แต่มีหน้าที่ตรงกันข้ามกัน โดย exit node จะส่ง traffic ทั้งหมดของอุปกรณ์ออกผ่าน VPS ทำให้ VPS กลายเป็นเส้นทางออกสู่สาธารณะของอุปกรณ์นั้น

สรุปได้ประโยคละหนึ่งใจความสำคัญดังนี้ subnet router ช่วยให้เครือข่ายส่วนตัวหนึ่งเครือข่ายสามารถเข้าถึงได้จาก tailnet ส่วน exit node ทำหน้าที่เปลี่ยนจุดที่ traffic สาธารณะของคุณออกสู่ภายนอก หากคุณต้องการใช้งาน exit node โปรดอ่าน วิธีการรัน Tailscale exit node บน VPS แทน ทั้งสองฟีเจอร์นี้ใช้ flag ที่แยกจากกัน แม้ว่า VPS หนึ่งเครื่องจะสามารถทำหน้าที่ทั้งสองอย่างพร้อมกันได้ แต่ทั้งสองฟีเจอร์แก้ปัญหาที่แตกต่างกันและมีสาเหตุความล้มเหลวที่ต่างกัน

เมื่อ VPS จำเป็นต้องทำหน้าที่เป็น subnet router

กรณีที่พบบ่อยคือเครือข่ายส่วนตัว (private network) ที่ผู้ให้บริการจัดเตรียมไว้ให้ VPS ของคุณจะมีที่อยู่สาธารณะ (public address) และอินเทอร์เฟซที่สองบนเซกเมนต์ส่วนตัว ในขณะที่เซิร์ฟเวอร์อื่นบนเซกเมนต์นั้นไม่มีที่อยู่สาธารณะเลย เช่น ฐานข้อมูลที่ 10.0.0.20 หรือเป้าหมายสำหรับสำรองข้อมูลที่ 10.0.0.30 ให้ติดตั้ง Tailscale บน VPS หนึ่งเครื่อง ประกาศเส้นทาง 10.0.0.0/24 แล้วแล็ปท็อปของคุณจะสามารถเข้าถึงที่อยู่ส่วนตัวเหล่านั้นได้โดยตรง โดยไม่ต้องเปลี่ยนแปลงค่าใดๆ บนเซกเมนต์นั้น และฐานข้อมูลก็ยังคงไม่มีที่อยู่สาธารณะ หากสิ่งเดียวที่คุณต้องการจากเซกเมนต์นั้นคือเว็บแอปพลิเคชันเดียวบนพอร์ตเดียว การประกาศเส้นทางทั้งช่วงถือว่าเกินความจำเป็น และ Tailscale serve จะช่วยทำ HTTPS บนพอร์ตนั้นพอร์ตเดียวแทน ตรรกะเดียวกันนี้ยังใช้กับ daemon ที่ตั้งใจให้เชื่อมต่อเฉพาะ localhost เท่านั้น เช่น dsh ที่รันแบบ headless ภายใต้ systemd ซึ่งที่อยู่บน tailnet ของ VPS นั้นจะเข้ามาแทนที่ SSH tunnel ที่คุณต้องเปิดค้างไว้เพื่อเข้าถึง UI

อีกกรณีหนึ่งคือเครือข่ายที่อยู่อีกฝั่งของ VPS เช่น LAN (local area network) ที่บ้านหรือที่ทำงานซึ่งอยู่หลังเราเตอร์ของตนเอง หรือกลุ่มอุปกรณ์ที่ไม่สามารถรัน Tailscale ได้เลย เช่น managed switch หรือ NAS รุ่นเก่าที่มีเฟิร์มแวร์แบบล็อกไว้ เครื่อง Linux เครื่องหนึ่งบนเครือข่ายนั้นจะทำหน้าที่เป็น subnet router ให้กับอุปกรณ์อื่นๆ ทั้งหมด สำหรับที่บ้าน เครื่องนั้นมักจะเป็น VM ขนาดเล็กบน hypervisor ที่คุณใช้งานอยู่แล้ว และ การคำนวณความคุ้มค่าระหว่างการใช้ Proxmox host ที่บ้านกับการเช่า VPS คือสิ่งที่คุณต้องตัดสินใจก่อนเลือกฝั่งที่จะวางบริการของคุณ

ทั้งสองกรณีมีข้อกำหนดร่วมกันประการหนึ่ง คือ subnet router ต้องสามารถเข้าถึงช่วงเครือข่ายที่ประกาศไว้ได้อยู่แล้ว โดยใช้ตารางเส้นทาง (routing table) และไฟร์วอลล์ของตนเอง Tailscale ไม่ได้สร้างการเชื่อมต่อนั้นขึ้นมาเอง แต่ทำหน้าที่ส่งผ่านทราฟฟิกไปยังเราเตอร์และส่งต่อให้ kernel เป็นผู้จัดการการส่งต่อข้อมูล (forward) ต่อไป

ติดตั้ง Tailscale และตรวจสอบเส้นทางเครือข่ายภายในก่อน

curl -fsSL https://tailscale.com/install.sh | sh

สคริปต์จะตรวจหา distribution เพิ่ม package repository ของ Tailscale ติดตั้งคำสั่ง tailscale และ daemon tailscaled จากนั้นจึงเปิดใช้งาน service ให้ยืนยันสถานะด้วย systemctl is-active tailscaled ซึ่งควรแสดงผลเป็น active

ก่อนดำเนินการอื่นใด ให้ตรวจสอบว่า VPS สามารถเข้าถึงเครือข่ายที่คุณต้องการประกาศใช้งานได้จริง

ip route show
ping -c3 10.0.0.20

ip route show ต้องแสดงช่วง IP ภายในบนอินเทอร์เฟซจริง เช่น 10.0.0.0/24 dev enp7s0 proto kernel scope link src 10.0.0.5 หากการ ping ล้มเหลวในขั้นตอนนี้บนตัวเราเตอร์เอง จะไม่มี flag ใดของ Tailscale ที่แก้ไขปัญหานี้ได้ ปัญหาเกิดจากการตั้งค่าเครือข่ายของ VPS หรือ firewall บนโฮสต์ปลายทาง ให้แก้ไขส่วนนั้นก่อน เนื่องจากการทดสอบในขั้นตอนถัดไปทั้งหมดขึ้นอยู่กับจุดนี้

เปิดใช้งาน IP forwarding และตั้งค่าให้คงอยู่หลังการรีบูต

เครื่อง Linux จะทิ้งแพ็กเก็ตใดก็ตามที่ไม่ได้ส่งถึงตัวมันเองหากไม่ได้เปิดใช้งานการส่งต่อ (forwarding) การส่งต่อแพ็กเก็ตของเครื่องอื่นเป็นหน้าที่หลักของ subnet router ดังนั้นขั้นตอนนี้จึงเป็นสิ่งที่ขาดไม่ได้

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

ตรวจสอบสถานะด้วย sysctl net.ipv4.ip_forward ซึ่งควรแสดงผลลัพธ์เป็น net.ipv4.ip_forward = 1

ผู้ใช้งานมักทำขั้นตอนนี้ไม่ครบถ้วน การใช้ sudo sysctl -w net.ipv4.ip_forward=1 จะเห็นผลทันทีแต่จะหายไปเมื่อรีบูตเครื่อง ทำให้ subnet router ทำงานได้ปกติหลายสัปดาห์แล้วหยุดทำงานทันทีหลังจากรีบูตเพื่ออัปเกรดเคอร์เนล ส่วนที่น่าสับสนคือไม่มีสัญญาณบ่งบอกว่าระบบเสียหาย tailscale status ยังคงแสดงสถานะว่าโหนดออนไลน์อยู่, admin console ยังคงแสดงว่าเส้นทาง (route) ได้รับการอนุมัติ และฝั่งไคลเอนต์ยังคงติดตั้งเส้นทางนั้นไว้ แพ็กเก็ตจะถูกส่งมาถึง VPS แต่เคอร์เนลจะทิ้งแพ็กเก็ตเหล่านั้นโดยไม่มีการบันทึก log ใดๆ การเขียนค่าลงใน /etc/sysctl.d/99-tailscale.conf คือสิ่งที่ทำให้การตั้งค่านี้คงอยู่หลังการรีบูต

หากคุณประกาศเส้นทาง (advertise routes) ในขณะที่ยังปิด forwarding อยู่ tailscale up จะแจ้งเตือนคุณในขณะนั้น สำหรับ Linux บรรทัดดังกล่าวจะคล้ายกับ Warning: IP forwarding is disabled, subnet routing/exit nodes will not work. โปรดอ่านผลลัพธ์ของคำสั่งนั้นแทนการเลื่อนผ่านไป

sudo tailscale up --advertise-routes=10.0.0.0/24

บน VPS ที่ลงชื่อเข้าใช้ tailnet อยู่แล้ว ให้เปลี่ยนการตั้งค่าในตำแหน่งเดิมแทน:

sudo tailscale set --advertise-routes=10.0.0.0/24

ให้ใช้ tailscale set สำหรับการเปลี่ยนแปลงในภายหลังทุกครั้ง การรัน tailscale up ซ้ำด้วย flag เพียงตัวเดียวจะรีเซ็ต flag อื่นๆ ที่คุณไม่ได้ระบุไว้ และ CLI จะหยุดการทำงานพร้อมแสดงข้อผิดพลาดว่าการเปลี่ยนการตั้งค่าด้วยวิธีนี้จำเป็นต้องระบุ flag ที่ไม่ใช่ค่าเริ่มต้นทั้งหมด ส่วน tailscale set จะเปลี่ยนการตั้งค่าเพียงรายการเดียวและคงค่าอื่นไว้ตามเดิม

คุณสามารถระบุช่วงเครือข่ายหลายรายการในรายการเดียวโดยคั่นด้วยเครื่องหมายจุลภาคและไม่มีช่องว่าง เช่น --advertise-routes=10.0.0.0/24,192.168.50.0/24 แต่ละรายการต้องเป็นที่อยู่เครือข่ายในรูปแบบ CIDR (classless inter-domain routing หรือรูปแบบ 10.0.0.0/24) หากคุณระบุที่อยู่ host ของตนเองโดยผิดพลาด เช่น 10.0.0.5/24 ระบบจะปฏิเสธเนื่องจากบิตหลัง prefix ไม่เป็นศูนย์ และข้อความแสดงข้อผิดพลาดจะระบุ prefix ที่คุณน่าจะต้องการสื่อถึง หากต้องการหยุดการประกาศเส้นทาง ให้ตั้งค่าเป็นรายการว่างด้วย sudo tailscale set --advertise-routes=

อนุมัติเส้นทางในคอนโซลผู้ดูแลระบบ

การประกาศเส้นทาง (advertising a route) เป็นเพียงการส่งคำขอ ไม่ใช่การเปลี่ยนแปลงค่าทันที จนกว่าผู้ดูแลระบบจะอนุมัติ ไคลเอนต์จะยังไม่ได้รับเส้นทางนั้นและไม่สามารถเข้าถึงช่วงเครือข่ายดังกล่าวได้ การออกแบบนี้มีเจตนาเพื่อความปลอดภัย เนื่องจากเครื่องที่สามารถเพิ่มตัวเองเข้าไปในตารางเส้นทางของทุกคนได้นั้น อาจดักจับทราฟฟิกของช่วงเครือข่ายใดก็ได้ตามต้องการ

ให้ดำเนินการอนุมัติที่หน้า Machines ในคอนโซลผู้ดูแลระบบ โดย VPS จะแสดงรายการพร้อมป้ายกำกับ subnet ให้เปิดแถวของเครื่องนั้น ค้นหาส่วน subnets แก้ไขการตั้งค่าเส้นทาง ทำเครื่องหมายถูกที่เส้นทางดังกล่าว แล้วบันทึก

การอนุมัติจะทำแยกตาม prefix หากคุณประกาศ 10.0.0.0/24 ในวันนี้ และประกาศ 192.168.50.0/24 ในเดือนหน้า prefix ใหม่จะเข้ามาในสถานะยังไม่อนุมัติ ในขณะที่ prefix เก่าจะยังคงทำงานได้ตามปกติ เส้นทางที่ได้รับอนุมัติและเส้นทางที่ถูกละเว้นจะมีสถานะเหมือนกันเมื่อดูจากฝั่ง VPS ดังนั้นควรตรวจสอบคอนโซลก่อนเริ่มขั้นตอนการแก้ไขปัญหาอื่น

คุณสามารถข้ามขั้นตอนการทำด้วยตนเองได้โดยใช้บล็อก autoApprovers ในไฟล์นโยบาย tailnet:

{
  "autoApprovers": {
    "routes": {
      "10.0.0.0/24": ["tag:subnet-router"]
    }
  }
}

จากนั้นให้เริ่มการทำงานของโหนดด้วยแท็กดังกล่าว sudo tailscale up --advertise-routes=10.0.0.0/24 --advertise-tags=tag:subnet-router แล้วเส้นทางจะถูกอนุมัติทันทีที่ประกาศออกมา ทั้งนี้ แท็กดังกล่าวจะต้องมีอยู่ในส่วน tagOwners ของไฟล์นโยบายเดียวกันก่อน การตั้งค่านี้มีประโยชน์หากคุณสร้าง VPS ใหม่จากสคริปต์ เนื่องจากโหนดที่ถูกสร้างใหม่จะถือเป็นโหนดใหม่ และเส้นทางของมันจะเริ่มต้นในสถานะยังไม่อนุมัติเสมอ

เหตุใดไคลเอนต์ Linux จึงเพิกเฉยต่อเส้นทางหากไม่มีแฟล็ก --accept-routes

เส้นทางดังกล่าวได้รับการประกาศและอนุมัติแล้ว โทรศัพท์และ Mac ของคุณสามารถเข้าถึง 10.0.0.20 ได้ แต่แล็ปท็อป Linux ของคุณกลับทำไม่ได้ และในคอนโซลผู้ดูแลระบบก็ไม่พบข้อบ่งชี้ถึงปัญหาใดๆ

การยอมรับ subnet route หมายถึงการเขียนรายการลงในตารางเส้นทาง (routing table) ของไคลเอนต์ บน Android, iOS, macOS, tvOS และ Windows ไคลเอนต์ Tailscale จะดำเนินการส่วนนี้ให้คุณโดยอัตโนมัติ แต่บน Linux จะไม่ทำเช่นนั้น เนื่องจากเครื่อง Linux มักเป็นเซิร์ฟเวอร์หรือเราเตอร์ที่มีการตั้งค่าตารางเส้นทางไว้อย่างเจาะจง การแทรก /24 ที่ได้รับมาจากเครือข่ายโดยไม่แจ้งเตือนอาจทำให้การรับส่งข้อมูลที่เครื่องนั้นจัดการอยู่เดิมเกิดปัญหาได้ ดังนั้นบน Linux คุณจึงต้องเลือกเปิดใช้งานด้วยตนเองในไคลเอนต์แต่ละเครื่อง:

sudo tailscale set --accept-routes

จากนั้นตรวจสอบว่าเส้นทางถูกเพิ่มเข้าไปที่ใด:

ip route show table 52
ip route get 10.0.0.20

Tailscale บน Linux จะไม่นำเส้นทางที่ยอมรับไปใส่ไว้ในตารางเส้นทางหลัก (main routing table) แต่จะนำไปใส่ไว้ในตารางเส้นทางหมายเลข 52 และติดตั้งกฎนโยบาย (policy rules) ซึ่งสามารถดูได้ด้วย ip rule show ในช่วงลำดับความสำคัญ 5210 ถึง 5270 เพื่อส่งแพ็กเก็ตที่ไม่ตรงกับเงื่อนไขไปยังตารางนั้น ดังนั้นการใช้ ip route show เพียงอย่างเดียวจะไม่แสดง 10.0.0.0/24 และผู้ที่ตรวจสอบด้วยคำสั่งนั้นเพียงอย่างเดียวอาจสรุปผิดว่า --accept-routes ไม่ได้ทำงานใดๆ ip route show table 52 คือคำสั่งที่แสดงข้อมูลที่ถูกต้อง และควรแสดงช่วงที่ประกาศไว้บน tailscale0

มีข้อยกเว้นประการหนึ่งที่ควรทราบ หากโหนด Linux นี้ทำหน้าที่เป็น subnet router ตัวที่สองสำหรับเครือข่ายท้องถิ่นของตนเอง การใช้ --accept-routes จะทำให้เครื่องส่งข้อมูลสำหรับ subnet ที่เชื่อมต่อโดยตรงของตนเองผ่านเราเตอร์ตัวอื่นแทนที่จะส่งออกผ่านอินเทอร์เฟซของตนเอง สำหรับเราเตอร์ในโหมดสำรอง (standby) ในระบบที่มีความพร้อมใช้งานสูง (high availability) ให้ปิด --accept-routes ไว้และทำการประกาศเส้นทางเพียงอย่างเดียว

โหมดความล้มเหลว: เราเตอร์สองตัวประกาศช่วง IP ซ้อนทับกัน

เราเตอร์ subnet สองตัวสามารถประกาศช่วง IP ที่เหมือนกันได้ ซึ่งเป็นวิธีการทำงานของระบบ high availability โดยเราเตอร์แต่ละตัวจะประกาศ prefix ชุดเดียวกันทุกประการ เพื่อให้ไคลเอนต์สามารถสลับการทำงาน (failover) ไปยังอีกตัวหนึ่งได้ นอกจากนี้ยังอนุญาตให้ช่วง IP ซ้อนทับกันโดยมี prefix length ต่างกันได้ โดย Tailscale จะเลือกเส้นทางที่เฉพาะเจาะจงที่สุด หากเราเตอร์ A ประกาศ 10.0.0.0/24 และเราเตอร์ B ประกาศ 10.0.0.0/16 ทราฟฟิกที่มุ่งหน้าไปยัง 10.0.0.20 จะถูกส่งไปยัง A

สิ่งที่มักทำให้ผู้ใช้ประหลาดใจคือพฤติกรรมเมื่อ A ออฟไลน์ Tailscale จะไม่ย้อนกลับไปใช้เส้นทางที่กว้างกว่า เพราะเราเตอร์ที่ออฟไลน์ไม่สามารถยกเลิกการประกาศเส้นทางได้ และไคลเอนต์จะยังคงเลือกใช้ prefix ที่เฉพาะเจาะจงกว่าเดิม ทราฟฟิกที่มุ่งหน้าไปยัง 10.0.0.20 จะหยุดทำงาน ในขณะที่ทราฟฟิกไปยัง 10.0.1.20 ซึ่งครอบคลุมเฉพาะโดย /16 ของ B จะยังคงทำงานผ่าน B ได้ตามปกติ อาการที่เกิดขึ้นจะดูเหมือนเครือข่ายส่วนตัวบางส่วนล่ม โดยมีสาเหตุมาจากโหนดที่ออฟไลน์ยังคงถือครอง prefix ที่เฉพาะเจาะจงกว่าไว้ หากคุณต้องการระบบ failover ให้ตั้งค่าเราเตอร์ที่ครอบคลุมช่วงกว้างกว่าให้ประกาศ prefix ที่แคบกว่าด้วย เพื่อให้ทั้งสองตัวครอบคลุมที่อยู่ชุดเดียวกัน

การซ้อนทับอีกรูปแบบหนึ่งเกิดขึ้นใกล้กับไคลเอนต์มากกว่า การใช้งานเครือข่ายโรงแรมที่ 192.168.1.0/24 ในขณะที่ subnet router ของคุณประกาศ 192.168.1.0/24 หมายความว่าทั้งสองแหล่งกำลังแย่งชิงปลายทางเดียวกัน ซึ่งผลลัพธ์จะขึ้นอยู่กับแพลตฟอร์ม บน Linux คุณสามารถติดตั้งกฎ (rule) ไว้ก่อนกฎของ Tailscale เพื่อให้ที่อยู่ภายในเครื่องใช้ตารางหลัก (main table):

sudo ip rule add to 192.168.1.0/24 priority 2500 lookup main

กฎดังกล่าวจะไม่คงอยู่ถาวรและจะหายไปเมื่อรีบูตเครื่อง วิธีแก้ไขที่แท้จริงคือการเลือกช่วง IP ส่วนตัวที่คุณจะไม่พบในเครือข่ายสาธารณะ 192.168.0.0/24 และ 192.168.1.0/24 เป็นค่าเริ่มต้นบนเราเตอร์ตามบ้านส่วนใหญ่ ดังนั้นควรเลือกช่วง IP ภายใน 10.0.0.0/8 ที่คุณกำหนดขึ้นเองอย่างตั้งใจ การชนกันของ IP ในลักษณะเดียวกันนี้จะทำให้ VPN แบบ WireGuard ที่คุณตั้งค่าด้วยตนเอง ใช้งานไม่ได้ด้วยเหตุผลเดียวกัน คือเส้นทางภายในเครื่องที่เฉพาะเจาะจงกว่าจะเป็นฝ่ายชนะ ทำให้ทราฟฟิกไม่ถูกส่งเข้าอุโมงค์ VPN

รูปแบบความล้มเหลว: DNS แปลงชื่อเป็นที่อยู่ซึ่งไม่มีเส้นทางรองรับ

ปัญหานี้ตรวจสอบได้ยากเนื่องจากไม่มีการรายงานข้อผิดพลาดใดๆ ชื่อโดเมนถูกแปลงเป็น IP ได้สำเร็จ แต่การเชื่อมต่อกลับหมดเวลา (timeout)

สมมติว่า db.internal.example.com ถูกแปลงเป็น 10.0.5.20 ผ่านเนมเซิร์ฟเวอร์ส่วนตัวของคุณ และคุณได้ประกาศเส้นทาง 10.0.0.0/24 ไว้ การค้นหาชื่อจะสำเร็จเพราะขั้นตอนการแปลงชื่อ (DNS - domain name system) และการกำหนดเส้นทาง IP (IP routing) เป็นคนละส่วนกันและไม่มีส่วนใดตรวจสอบความถูกต้องของอีกส่วน จากนั้นแพ็กเก็ตที่ส่งไปยัง 10.0.5.20 จะไม่พบเส้นทางที่ตรงกันใน tailnet จึงหลุดออกไปทาง default gateway ของไคลเอนต์และหายไปในที่สุด

คำสั่งสองชุดนี้จะช่วยแยกแยะปัญหาทั้งสองส่วนออกจากกัน:

nslookup db.internal.example.com
ip route get 10.0.5.20

หากการค้นหาชื่อส่งคืนที่อยู่ IP กลับมา แต่ ip route get ไม่ตอบสนองด้วย dev tailscale0 แสดงว่าชื่อโดเมนถูกต้องแต่เส้นทางหายไป ให้ประกาศช่วง IP ที่ครอบคลุมที่อยู่นั้น โดยอาจใช้ 10.0.0.0/16 หรือระบุ prefix เพิ่มเติมอีกชุด จากนั้นอนุมัติ prefix ใหม่ในคอนโซล

มีกับดักที่คล้ายกันบนตัวเนมเซิร์ฟเวอร์เอง หากคุณตั้งค่าเนมเซิร์ฟเวอร์ส่วนกลางใน admin console เป็นที่อยู่ส่วนตัว เช่น 10.0.0.53 ที่อยู่นั้นจะต้องอยู่ภายในเส้นทางที่ได้รับอนุมัติ มิฉะนั้นอุปกรณ์ของคุณจะไม่สามารถเข้าถึงตัวแปลงชื่อ (resolver) ได้เลย หากคุณเปิดตัวเลือกที่บังคับใช้ DNS ส่วนกลางในขณะที่ชี้ไปยัง resolver ที่ไม่มีใครเข้าถึงได้ อุปกรณ์ทุกเครื่องใน tailnet จะสูญเสียความสามารถในการแปลงชื่อทันที รวมถึงเครื่องที่เพิ่งใช้งานได้เมื่อครู่ ให้ประกาศและอนุมัติเส้นทางไปยัง resolver ก่อน แล้วจึงค่อยเปลี่ยนการตั้งค่า DNS หากปัญหา DNS ภายในอุโมงค์ (tunnel) เป็นสิ่งที่คุณยังคงประสบอยู่ วิธีที่ DNS ล้มเหลวผ่านอุโมงค์ WireGuard จะอธิบายกลไกเดียวกันนี้โดยไม่มีเลเยอร์การประสานงานด้านบนมาเกี่ยวข้อง

Source NAT และการเชื่อมต่อแบบ site to site

โดยปกติแล้ว subnet router จะเขียนที่อยู่ต้นทางของทุกแพ็กเก็ตที่ส่งต่อใหม่ให้เป็นที่อยู่ส่วนตัวของตัวมันเอง กระบวนการนี้เรียกว่า SNAT (source network address translation) ซึ่งมีไว้เพื่อให้การตอบกลับทำงานได้โดยไม่ต้องแก้ไขค่าใดๆ บนเครือข่ายส่วนตัว เช่น ฐานข้อมูลที่ 10.0.0.20 จะตอบกลับไปยัง VPS ซึ่งเป็นปลายทางที่ฐานข้อมูลรู้จักวิธีเข้าถึงอยู่แล้ว ข้อเสียคือฐานข้อมูลจะมองเห็นการเชื่อมต่อ tailnet ทุกรายการว่ามาจาก VPS ทำให้กฎไฟร์วอลล์รายต้นทางและ log การเข้าถึงไม่สามารถระบุตัวตนผู้ใช้งานจริงได้

คุณสามารถปิดการทำงานนี้บน Linux ได้หากต้องการคงที่อยู่ tailnet จริงของไคลเอนต์ไว้:

sudo tailscale set --snat-subnet-routes=false

จากนั้นโฮสต์บนเครือข่ายส่วนตัวจำเป็นต้องมีเส้นทาง (route) กลับไปยัง 100.64.0.0/10 ซึ่งเป็นช่วงที่ Tailscale กำหนดให้กับอุปกรณ์ต่างๆ โดยต้องชี้ไปยัง subnet router หากไม่มีเส้นทางขากลับนี้ แพ็กเก็ตตอบกลับจะถูกส่งไปยัง default gateway และไปไม่ถึงปลายทาง ทำให้การเชื่อมต่อค้างหลังจากส่งแพ็กเก็ตแรก คุณต้องเพิ่ม static route บน gateway ของเครือข่ายส่วนตัว หรือเปิดใช้งาน SNAT ไว้ตามเดิม

การเชื่อมต่อแบบ site to site คือการที่ subnet router สองตัวทำงานนี้พร้อมกัน โดยแต่ละตัวจะประกาศเครือข่ายของตนเองและยอมรับเครือข่ายของอีกฝั่ง:

sudo tailscale up --advertise-routes=10.0.0.0/24 --snat-subnet-routes=false --accept-routes

ให้รันคำสั่งที่สอดคล้องกันบนเราเตอร์อีกตัวโดยใช้ช่วงเครือข่ายของตัวมันเอง ช่วงเครือข่ายทั้งสองต้องไม่ซ้ำกัน หากการถ่ายโอนข้อมูลขนาดใหญ่เกิดการหยุดชะงักในขณะที่ ssh และ ping ยังทำงานได้ปกติ สาเหตุอาจมาจาก MSS (maximum segment size) ซึ่งเป็นขนาดข้อมูลที่ใหญ่ที่สุดที่แพ็กเก็ต TCP สามารถบรรจุได้ ค่า overhead ของอุโมงค์ทำให้แพ็กเก็ตที่ถูกส่งต่อมีขนาดใหญ่เกินกว่าที่ลิงก์ระหว่างทางบางจุดจะรองรับได้ การทำ clamping จะช่วยแก้ไขปัญหานี้:

sudo iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

บันทึกกฎดังกล่าวด้วย iptables-persistent มิฉะนั้นกฎจะหายไปเมื่อมีการบูตเครื่องใหม่

การดูแลรักษาเพื่อให้ระบบทำงานได้อย่างต่อเนื่อง

โดยปกติแล้ว Node keys จะมีอายุการใช้งาน 180 วันนับตั้งแต่เดือนตุลาคม 2026 เป็นต้นไป เมื่อคีย์บน subnet router หมดอายุ โหนดจะออกจากระบบและช่วง IP ที่ประกาศไว้ทั้งหมดจะไม่สามารถเข้าถึงได้ โดยที่ไม่มีการเปลี่ยนแปลงการตั้งค่าใดๆ ที่อธิบายสาเหตุได้ ให้ปิดการหมดอายุของคีย์สำหรับเครื่องนี้ที่หน้า Machines ใน admin console จากนั้นให้จดบันทึกไว้ว่าคุณได้ดำเนินการแล้ว โหนดที่ถูกเปิดใช้งานภายใต้ tag ดังตัวอย่าง autoApprovers ด้านบน จะถูกปิดการหมดอายุของคีย์ไว้เป็นค่าเริ่มต้น

Tailscale จะพยายามเชื่อมต่อโดยตรงระหว่าง peer และจะเปลี่ยนไปใช้ relay servers เมื่อไม่สามารถเชื่อมต่อโดยตรงได้ แม้ relay จะทำงานได้ แต่ก็จะเพิ่มค่า latency กรณีของ VPS ที่มี public address นั้นทำได้ง่าย เพียงอนุญาต inbound UDP 41641 ส่วนใหญ่แล้ว peer ก็จะเชื่อมต่อได้โดยตรง เมื่อพบว่าการรับส่งข้อมูลไปยังช่วง private range ช้ากว่าที่ควรจะเป็นบน VPS การตรวจสอบว่าไคลเอนต์ของคุณเชื่อมต่อกับ subnet router โดยตรงหรือผ่าน relay คือสิ่งแรกที่ต้องทำเพื่อตัดประเด็นปัญหา หากคุณใช้ ufw ในการจัดการ firewall กฎ ufw ที่ VPS จำเป็นต้องใช้จริง จะอธิบายถึงรูปแบบคำสั่งที่ถูกต้อง

Access rules คืออีกส่วนที่สำคัญ ใน tailnet ค่าเริ่มต้น อุปกรณ์ทุกเครื่องของคุณสามารถเข้าถึงกันได้หมด ดังนั้น route ที่ได้รับอนุมัติจึงใช้งานได้ทันที แต่เมื่อคุณเขียน ACL policy ฝั่งปลายทางของกฎจะต้องระบุช่วง private range ให้ชัดเจน เพราะ 10.0.0.20 ไม่ใช่ที่อยู่ของ tailnet และไม่ครอบคลุมโดยกฎที่เขียนขึ้นสำหรับ tailnet IP หรือ tag

สุดท้าย ให้ตัดสินใจว่าคุณต้องการใช้ coordination server ที่คุณไม่ได้ดูแลเองหรือไม่ Tailscale control plane เป็นบริการแบบ hosted แม้คีย์จะยังคงอยู่บนเครื่องของคุณ แต่บัญชีและไฟล์ policy จะอยู่ที่นั่น สิ่งที่ผู้ไม่หวังดีอาจทำได้หาก control plane ถูกบุกรุกหรือข้อมูลล็อกอินถูกขโมย คือประเด็นที่ควรพิจารณาก่อนที่คุณจะอนุญาตให้เข้าถึงเครือข่ายส่วนตัวของคุณ และ โมเดลความน่าเชื่อถือของ Tailscale จะระบุขอบเขตดังกล่าวไว้ ค่าใช้จ่ายมักไม่ใช่สาเหตุหลักที่ทำให้คนเปลี่ยนไปใช้บริการอื่น เนื่องจาก แผนฟรีรองรับผู้ใช้สูงสุด 6 คนพร้อมอุปกรณ์ส่วนตัวไม่จำกัดจำนวน อย่างไรก็ตาม subnet router ที่คุณเปิดใช้งานภายใต้ tag จะถูกนับต่างจากโหนดที่ล็อกอินด้วยบัญชีของคุณ หลังจากจุดนั้นไป ค่าใช้จ่ายจะคิดตามจำนวนคนไม่ใช่จำนวนเครื่อง ดังนั้น สิ่งที่ครัวเรือนหรือทีมขนาด 5 คนต้องจ่ายจริงเมื่อแผนฟรีสิ้นสุดลง จึงเป็นเรื่องที่ควรคำนวณก่อนเพิ่มบัญชีที่จะทำให้คุณต้องเสียค่าใช้จ่าย การรัน Headscale ซึ่งเป็น Tailscale control server แบบ self-hosted จะช่วยให้คุณเก็บข้อมูลไว้บน VPS ของคุณเอง แต่ต้องแลกกับการที่ต้องดูแลระบบด้วยตนเอง อีกทางเลือกหนึ่งสำหรับความกังวลเดียวกันคือการเลิกใช้ไคลเอนต์ของ Tailscale แล้วหันไป self-hosting NetBird VPN server ซึ่งจะนำชั้น coordination และ mesh clients มาไว้บนเครื่องที่คุณควบคุมเอง หากคุณยังตัดสินใจไม่ได้ระหว่างโมเดลนี้กับการตั้งค่าด้วยตนเอง การเปรียบเทียบระหว่าง WireGuard และ Tailscale จะอธิบายว่าชั้น coordination มอบอะไรให้คุณและมีต้นทุนอย่างไรบ้าง

FAQ

Subnet router กับ exit node ต่างกันอย่างไร

Subnet router ทำหน้าที่ประกาศช่วงที่อยู่ IP ภายใน เพื่อให้เครื่องที่อยู่ใน tailnet สามารถเข้าถึงเครื่องที่ไม่ได้ติดตั้ง Tailscale ได้ ส่วน exit node ทำหน้าที่ประกาศตนเองเป็นเส้นทางออกสู่ Internet ทั้งหมด เพื่อให้เครื่องลูกข่ายส่ง traffic ทั้งหมดออกผ่านที่อยู่สาธารณะของ node นั้น VPS หนึ่งเครื่องสามารถเป็นได้ทั้งสองอย่าง โดยใช้ flag แยกกันคือ --advertise-routes และ --advertise-exit-node ซึ่งแต่ละรายการต้องได้รับการอนุมัติใน admin console แยกกัน

ทำไม Linux client ของฉันถึงไม่สนใจ subnet route ที่ประกาศไว้

Linux client จะไม่ยอมรับ subnet route จนกว่าคุณจะสั่งให้ทำ ให้รันคำสั่ง sudo tailscale set --accept-routes บน client จากนั้นตรวจสอบด้วย ip route show table 52 แทนที่จะใช้ ip route show เนื่องจาก Tailscale จะติดตั้ง route ที่ยอมรับไว้ใน routing table 52 และเข้าถึงผ่าน policy rules ทำให้ตารางหลัก (main table) ไม่แสดงรายการเหล่านี้ และดูเหมือนว่า route ที่ใช้งานได้จริงนั้นหายไป

ทำไม subnet ถึงหยุดทำงานหลังจากรีบูตเครื่อง

สาเหตุที่เป็นไปได้มากที่สุดคือ IP forwarding ค่าที่ตั้งไว้ด้วย sysctl -w จะไม่คงอยู่หลังการรีบูต ดังนั้นให้เขียนค่าลงใน /etc/sysctl.d/99-tailscale.conf และยืนยันด้วย sysctl net.ipv4.ip_forward หากเปิด forwarding แล้วแต่ยังเข้าถึงช่วง IP ไม่ได้ ให้ตรวจสอบ node ใน admin console โดยปกติ node keys จะหมดอายุหลังจาก 180 วัน และ subnet router ที่หมดอายุจะแสดงอาการเหมือนปัญหาเครือข่ายมากกว่าปัญหาบัญชีผู้ใช้

Subnet router สองตัวสามารถประกาศช่วง IP เดียวกันได้หรือไม่

ได้ การประกาศช่วง IP ที่เหมือนกันคือวิธีที่ทำให้ระบบ high availability ทำงานได้ โดย router ทั้งสองตัวจะประกาศ prefix ที่เหมือนกันทุกประการ ส่วนการประกาศช่วง IP ที่ซ้อนทับกันด้วยความยาว prefix ที่ต่างกันก็สามารถทำได้เช่นกัน โดยระบบจะเลือกใช้เส้นทางที่ระบุเจาะจงที่สุด (most specific) อย่างไรก็ตาม การทำ failover ต้องระมัดระวังในจุดนี้ เพราะเมื่อ router ที่ถือ prefix ที่เจาะจงกว่าออฟไลน์ไป Tailscale จะไม่ย้อนกลับไปใช้ route ที่กว้างกว่า ทำให้ traffic ส่วนนั้นหยุดทำงาน สำหรับการทำ standby pair ที่แท้จริง ควรให้ router ทั้งสองตัวประกาศ prefix ที่เจาะจงเหมือนกัน

ทำไม hostname ถึง resolve ได้แต่การเชื่อมต่อหมดเวลา (timeout)

การทำ DNS resolution และการทำ routing เป็นขั้นตอนที่แยกจากกัน ชื่อ host อาจ resolve ไปยังที่อยู่ที่ไม่มี route ใดที่ได้รับอนุมัติครอบคลุมถึง ทำให้ packet ถูกส่งออกผ่าน default gateway ของ client ให้รันคำสั่ง ip route get <address> บน client หากผลลัพธ์ไม่รวมถึง dev tailscale0 ให้ประกาศช่วง IP ที่ครอบคลุมที่อยู่นั้นและอนุมัติ prefix ใหม่ใน admin console