แจก static route ด้วย DHCP
ย้อนกลับมาที่งานที่โรงเรียนอีกครั้ง ช่วงนี้ถูกโทรตามบ่อยหน่อย เพราะกำลังเชื่อมเครือข่ายระหว่างโรงเรียนสองโรงในเครือเดียวกันเข้าด้วยกัน โดยพยายามใช้ทรัพยากรผ่าน LAN ร่วมกัน แต่ต่างฝ่ายต่างมีอินเทอร์เน็ตอยู่แล้ว
ยังไม่รู้แน่ว่าสุดท้ายจะใช้วิธีการไหน อาจจะรวมเป็น network เดียวกัน (โดยเปลี่ยนจาก class C มาเป็น class B หรือ A) หรือแยกเป็น subnet ก็ได้ แต่เมื่อวานก็เข้าไปทดสอบการเชื่อมเครือข่ายแบบแยก subnet โดยให้มี server เครื่องหนึ่งเป็น router โยงสองเครือข่ายเข้าด้วยกัน
ทีนี้ ก็ต้องมาเซ็ต routing ของเครือข่าย ให้ติดต่ออีก subnet ผ่าน router นี้ แต่ยังออก internet ด้วย gateway เดิม ซึ่งจากการทดลองกำหนด IP และ route table แบบ manual บนเครื่องลูกข่ายซึ่งเป็น WinXP และลินุกซ์ ก็สามารถใช้งานได้ทั้งสองทาง
ขั้นต่อไปคือ จะกำหนดจาก DHCP ได้อย่างไร เพราะจะให้ไปสั่งที่เครื่องต่างๆ ทุกเครื่อง ก็ไม่ไหว ลองถามใน #tlwg มีใครบางคนแนะนำว่า ให้ใช้ gateway ตัวเดียวในแต่ละวงก็พอ แล้วกำหนด route table ที่ gateway ให้ส่งต่อไปยัง router ที่ต้องการ แต่ปัญหาก็คือ เราต้องการแยก traffic ของ LAN กับของ internet ออกจากกัน เพราะ traffic ของ LAN จะค่อนข้างคับคั่ง ถ้ามาผ่าน gateway ร่วมกับ internet อาจเกิดการรบกวนกันได้
แต่อ่านคู่มือของ DHCP server ก็ไม่มีที่ไหนกล่าวถึงการแจก routing table มีแต่แจก gateway ได้หลายตัวเท่านั้น หรือว่าจะต้องใช้ gateway เดียวจริงๆ?
แต่ช้าก่อน RFC3442 มีการเพิ่ม classless static route option สำหรับ DHCP โดยอ้างไปถึง option 33 ของ RFC2132 ว่าเป็นการส่ง IP static route แบบ classful (คือ IP address จะ imply netmask ตามคลาส) แต่เนื่องจากไม่มีใครใช้ classful IP สักเท่าไรกันแล้ว option นี้ก็เลยจะถูกแทนที่ด้วย option 121 ตาม RFC3442
ลองไปค้นดูจาก man page ของ dhcp-options(5) ก็พบ option static_routes ที่ว่า โดยมีรูปแบบ argument เป็น sequence ของคู่ net-ip, router เรียงต่อกันไป สามารถกำหนดใน dhcpd.conf ของ DHCP server ได้ว่า:
option static-routes 192.168.1.0 192.168.0.3; option routers 192.168.0.1;
เพื่อระบุให้ใช้ 192.168.0.3 เป็น router ไปยังเครือข่าย 192.168.1.0/24 และให้ 192.168.0.1 เป็น default gateway สำหรับออกอินเทอร์เน็ตได้
แต่.. พอลองดูจริง ก็เป็นตามที่ man page บอก..
... Since classless IP routing is now the most widely deployed routing standard, this option is virtu- ally useless, and is not implemented by any of the popular DHCP clients, for example the Microsoft DHCP client.
คือจะได้ routing แบบ netmask 255.255.255.255 มาเลย ไม่ใช่อ้างทั้งเครือข่ายแบบที่ต้องการ (เท่าที่ search ดู solution ของ *BSD, Red Hat ก็ดูจะทำแบบนี้เหมือนกัน)
เลยต้องมุ่งมาที่ option 121 ของ RFC3442 แทน ซึ่งปรากฏว่า แกะ source ของ dhcp 3.0.3 แล้ว option นี้ยังเป็น "unknown-121" อยู่ คือไม่มี configuration option ให้ใช้!
แต่ google ก็ไม่ทิ้งเรา พาไปจนเจอ blog หนึ่ง ซึ่งเจ้าของเจอปัญหาเดียวกัน แล้วก็มีคนตอบให้ด้วย ก็เลยมาลองซะ..
# MS routes: adds extras to supplement routers option option ms-classless-static-routes code 249 = array of integer 8; # RFC3442 routes: overrides routers option option rfc3442-classless-static-routes code 121 = array of integer 8; option routers 192.168.0.1; option ms-classless-static-routes 24, 192,168,1, 192,168,0,3; option rfc3442-classless-static-routes 24, 192,168,1, 192,168,0,3;
เขา declare option ใช้เอง (โหะๆ เพิ่งรู้ว่าทำได้ด้วย) โดยกำหนด structure ของไบต์ข้อมูลตาม RFC3442 ไบต์แรกเป็นจำนวนบิตของ netmask, ถัดมาเป็น network address ที่ละค่า .0 ต่อท้าย คือในที่นี้ netmask 24 บิต ก็ใช้แค่สามไบต์ แล้วจากนั้นก็ตามด้วย IP ของ router โดยในที่นี้ ได้เพิ่ม vendor option 249 ของ MS ด้วย
ลองไป repair network connection ที่เครื่อง WinXP ลูกข่าย แล้ว "ROUTE PRINT" ดู โหะๆ มาแล้วแฮะ route table ที่ต้องการ!
แต่.. เครื่อง debian ลูกข่ายยังนิ่งเฉย..
เป็นเพราะ DHCP 3.0.3 ยังไม่ implement feature นี้นั่นเอง ก็เลยต้องไปเขียน dhclient-script เพิ่มเติมเอา ให้มันอ่านข้อมูล option 121 มาเซ็ต route table เริ่มจากแก้ /etc/dhcp3/dhclient-enter-hooks.d/debug ให้มันแสดงข้อมูลต่างๆ แล้วค้นหาชื่อตัวแปรที่มันส่งมาให้ จนพบว่า มันมาในชื่อ $new_unknown_121 ว่าแล้วก็นั่งเขียน shell script เพื่อ parse ข้อมูลแล้วสั่ง add route table เอา
..ผ่านจนได้ หุๆๆ (แต่ shell script ยังมั่วมาก เขียนแบบรีบๆ)