ใช้ BIRD 1.6.x เป็น Route Server สำหรับ Internet Exchange Point (IXP)

Use BIRD 1.6.x as Route Server for Internet Exchange Point (IXP)

Nopnithi Khaokaew (Game)
8 min readJun 20, 2020

— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —

Internet Exchange Point (IXP) คืออะไร?

สำหรับ internet exchange point หรือที่ชอบเรียกย่อ ๆ กันว่า IXP นั้นเป็นสถานที่ และโดยส่วนมากจะเป็น data center ที่ซึ่งผู้ให้บริการอินเตอร์เน็ต (ISP - Internet Service Provider) หรือ CDN (Content Delivery Network) หลาย ๆ เจ้ามาเชื่อมต่อกันโดยตรง

เมื่อเป็นอย่างนี้แล้วแทนที่ traffic ของผู้ใช้อย่างเราที่ปกติจะต้องวิ่งไปบนอินเตอร์เน็ตซึ่งมีระยะทางที่ไกล, ต้องผ่านอุปกรณ์หลาย node หรือบางครั้งก็อาจจะวิ่งอ้อมไปบ้างก็จะไม่เกิดขึ้นแล้ว เนื่องจาก traffic ของผู้ใช้จาก ISP 1 สามารถวิ่งไปยังปลายทางที่อยู่ข้างหลังของ ISP 2 ได้โดยตรงผ่าน IXP

ผลก็คือค่าใช้จ่ายที่ลดลงเพราะไม่ต้องมีการแลกเปลี่ยน traffic ระหว่าง ISP ต่าง ๆ รวมถึงในแง่ของ user experience ก็จะดีขึ้นเพราะ latency หรือ round-trip time นั้นลดลง

ถ้าไม่เห็นภาพผมแนะนำให้ดูวิดีโอของ BKNIX ครับ เค้าทำออกมาได้ดีจริง ๆ

ขอบคุณวิดีโอจาก Bangkok Neutral Internet Exchange (BKNIX) ครับ

ตัวอย่าง IXP แบบง่าย ๆ

จากรูปจะเห็นว่า ISP แต่ละเจ้าจะเชื่อมต่อหากันผ่านทาง IXP switch ซึ่งตั้งอยู่ภายใน data center เดียวกัน (L2 domain เดียวกัน) ถ้าเรามี ISP มาเพิ่มอีก 100 เจ้าก็แค่จิ้มเข้ากับ switch, configure IP ให้อยู่ใน network เดียวกันแล้ว peer BGP กับ route server แค่นั้นเอง

โดย ISP แต่ละเจ้าก็จะ advertise prefix (network) ที่ตัวเองรู้จักออกไปให้ route server ในทางกลับกันฝั่ง route server ก็จะเป็นตัวกลางในการส่งผ่าน prefix เหล่านั้นให้กับ ISP อื่นที่เป็น neighbor ของมันอีกที ดังนั้น traffic ระหว่าง ISP จะวิ่งหากันตรง ๆ โดยไม่ต้องทำ routing เลย

Route Server คืออะไร?

Route server คือ server ทั่ว ๆ ไปที่ install software จำพวก routing daemon ลงไป ทำให้มันมีความสามารถในการใช้งาน routing protocol ต่าง ๆ ได้เหมือนกับ router

การใช้งาน Route Server ใน IXP

ถ้าหากว่า IXP ของเราไม่มี route server เข้ามาช่วยเรื่อง BGP peering จะเกิดความยุ่งยากประมาณนี้

  • BGP session มีจำนวนมาก เพราะต้อง peer กันเป็น full mesh โดยจำนวน session ของแต่ละ member คือ n*(n-1)/2 ซึ่ง n คือจำนวนของ member ใน IXP
  • เมื่อมี member ใหม่เข้าร่วม ทุกคนจะต้อง re-configure อุปกรณ์ของตัวเอง
  • แน่นอนว่าเมื่อ neighbor เยอะ ก็กิน CPU resource ของ router ไล่ไปตั้งแต่เรื่องของการ maintain BGP session ไปจนถึง route update

แต่พอมี route server เข้ามาช่วยเราก็จะกำจัดปัญหาข้างบนไปได้ทั้งหมด

  • BGP session ต่อ member เหลือแค่ 1 session (กรณีมี route server 1 ตัว)
  • เมื่อมี member ใหม่เข้ามา คนอื่นก็ไม่ต้อง configure อะไรเพิ่มเติม
  • สามารถ filter/manage route ได้ง่ายขึ้นเพราะทำบน route server แค่ตัวเดียว

ถ้าใครเล่น BGP มาบ้างจะรู้สึกเหมือนผมว่า route server มีหลักการและประโยชน์คล้ายกับเทคนิคหนึ่งของ BGP ที่เรียกว่า BGP route relector ครับ (คล้ายเฉย ๆ แต่ไม่เหมือนซะทีเดียว)

วิธี Install BIRD (Routing Daemon) บน Ubuntu 18.04

ถ้าเอาง่ายเข้าว่าก็ให้ใช้ command นี้ครับ (ใช้ root user ก่อนนะ)

apt update && apt upgrade -y && apt install bird -y

แต่เราจะไม่ได้ BIRD เวอร์ชั่นล่าสุด (ณ วันที่ผมเขียนนี้เป็น BIRD 1.6.3 ซึ่ง release มาตั้งแต่ 22 Dec 2016 ละ) ดังนั้นผมแนะนำให้ manual install เอาดีกว่า

โดยก่อนอื่นให้ไปเช็คเวอร์ชั่นล่าสุดที่นี่

https://bird.network.cz/?download

จะเห็นว่าเค้าแยกพัฒนาเป็น 2 เวอร์ชั่น คือ 1.6 กับ 2.0 ครับ โดยมือใหม่ผมแนะนำว่าให้ใช้ 1.6 ก่อน เพราะมันมีข้อมูลต่าง ๆ บนอินเตอร์เน็ตให้เรียนรู้ได้เยอะกว่า

apt update
apt install -y libncurses-dev libreadline-dev bison flex
wget https://bird.network.cz/download/bird-1.6.8.tar.gz
tar -xzf bird-1.6.8.tar.gz && cd bird-1.6.8
./configure
make
make install

จริง ๆ ถ้าใครช่ำ Docker แนะนำให้สร้าง image มาใช้เป็นแบบ container แทน native-VM ก็ไม่เลวครับ และผมก็แนะนำท่านี้มากกว่าด้วย

ไฟล์ Configuration ของ BIRD

หลัง install เสร็จ พวก configuration จะอยู่ที่ /usr/local/etc/ ครับ

IPv4 Configuration

/usr/local/etc/bird.conf

IPv6 Configuration

/usr/local/etc/bird6.conf

วิธีการ Run BIRD และเข้าใช้งาน BIRD CLI

ในหน้า terminal ให้ทำการ run BIRD ก่อนครับ

bird

จากนั้นเข้า CLI ด้วย command นี้

birdc

ถ้าเห็นหน้าตาแบบนี้ก็แปลว่าการติดตั้ง BIRD เป็นอันเรียบร้อย

การ Configure อุปกรณ์ต่าง ๆ

ผมขอละในส่วนของการ configure พวกรายละเอียดยิบย่อยบน Ubuntu ไปนะ เพราะในเบื้องต้นก็แค่ configure IP บน interface ที่เชื่อมต่อกับ IXP switch แค่นั้นเอง

Configure BGP บน BIRD เป็น Route Server

เอาไปแปะไว้ที่นี่ /usr/local/etc/bird.conf หรือถ้าอยาก run โดยใช้ config จาก path อื่นก็ pass argument แบบนี้ bird -c <config-file>

log "/var/log/bird.log" all;
log syslog all;

router id 100.1.1.100;
define myas = 555;

protocol device { }

# This function excludes weird networks
# rfc1918, class D, class E, too long and too short prefixes
function avoid_martians()
prefix set martians;
{
martians = [ 169.254.0.0/16+, 172.16.0.0/12+, 192.168.0.0/16+, 10.0.0.0/8+,
224.0.0.0/4+, 240.0.0.0/4+, 0.0.0.0/32-, 0.0.0.0/0{25,32}, 0.0.0.0/0{0,7} ];

# Avoid RFC1918 and similar networks
if net ~ martians then return false;

return true;
}

# BGP output filter (based on communities)
function bgp_out_comm(int peeras)
{
if ! (source = RTS_BGP ) then return false;

if peeras > 65535 then
{
if (ro,0,peeras) ~ bgp_ext_community then return false;
if (ro,myas,peeras) ~ bgp_ext_community then return true;
} else {
if ((0,peeras) ~ bgp_community) || ((ro,0,peeras) ~ bgp_ext_community) then return false;
if ((myas,peeras) ~ bgp_community) || ((ro,myas,peeras) ~ bgp_ext_community) then return true;
}

if ((0,myas) ~ bgp_community) || ((ro,0,myas) ~ bgp_ext_community) then return false;

return true;
}

function bgp_out(int peeras)
{
if !bgp_out_comm(peeras) then return false;

# Remove IXP related communities
bgp_community.delete([(0,*)]);
bgp_community.delete([(myas,*)]);

bgp_ext_community.delete([(ro,0,*)]);
bgp_ext_community.delete([(ro,myas,*)]);

return true;
}

####
# Protocol templates
template bgp PEERS {
local as myas;
rs client;
secondary;
import limit 25000 action restart;
start delay time 60;
interpret communities off;
import keep filtered on;
}

table master sorted;

####
# Configuration of BGP peer follows

### AS1 - ISP1
filter bgp_in_AS1
prefix set allnet;
int set allas;
{
if ! (avoid_martians()) then reject;
if (bgp_path.first != 1 ) then reject;

allnet = [ 1.1.1.0/24, 11.11.0.0/16 ];
if ! (net ~ allnet) then reject;

accept;
}

protocol bgp AS1x1 from PEERS {
description "ISP 1 - Peer 1";
neighbor 100.1.1.1 as 1;
import filter bgp_in_AS1;
export all;
}

### AS2 - ISP2
filter bgp_in_AS2
prefix set allnet;
int set allas;
{
if ! (avoid_martians()) then reject;
if (bgp_path.first != 2 ) then reject;

allnet = [ 2.2.2.0/24, 22.22.0.0/16 ];
if ! (net ~ allnet) then reject;

accept;
}

protocol bgp AS2x1 from PEERS {
description "ISP 2 - Peer 1";
neighbor 100.1.1.2 as 2;
import filter bgp_in_AS2;
export all;
}

หลัก ๆ ก็คือมีการกำหนด router id, AS number ของ route server, reject route ที่เป็น private IP, เขียน logic ในเรื่องของ BGP community ว่าถ้าเจอ community แบบไหนให้ทำอะไร, แล้วก็สร้าง filter เพื่อเลือกรับเฉพาะ route ที่กำหนดจาก ISP ประมาณนี้ครับ

Configure Cisco Router เพื่อ Peer BGP กับ BIRD (Route Server)

ISP1 Configuration

interface Loopback0
ip address 1.1.1.1 255.255.255.0
!
interface Loopback1
ip address 11.11.11.11 255.255.0.0
!
interface Ethernet0/0
ip address 100.1.1.1 255.255.255.0
no shutdown
!
router bgp 1
no bgp enforce-first-as
bgp log-neighbor-changes
bgp deterministic-med
no bgp default ipv4-unicast
neighbor NOPNITHI-NIX-RS-v4 peer-group
neighbor NOPNITHI-NIX-RS-v4 remote-as 555
neighbor NOPNITHI-NIX-RS-v4 description NOPNITHI-NIX-RS-IPv4
neighbor 100.1.1.100 remote-as 555
neighbor 100.1.1.100 peer-group NOPNITHI-NIX-RS-v4
neighbor 100.1.1.100 description Route-Server
!
address-family ipv4
network 1.1.1.0 mask 255.255.255.0
network 11.11.0.0 mask 255.255.0.0
neighbor NOPNITHI-NIX-RS-v4 send-community both
neighbor NOPNITHI-NIX-RS-v4 next-hop-self
neighbor NOPNITHI-NIX-RS-v4 remove-private-as
neighbor NOPNITHI-NIX-RS-v4 maximum-prefix 10000
neighbor 100.1.1.100 activate
exit-address-family

ISP2 Configuration

interface Loopback0
ip address 2.2.2.2 255.255.255.0
!
interface Loopback1
ip address 22.22.22.22 255.255.0.0
!
interface Ethernet0/0
ip address 100.1.1.2 255.255.255.0
no shutdown
!
router bgp 2
no bgp enforce-first-as
bgp log-neighbor-changes
bgp deterministic-med
no bgp default ipv4-unicast
neighbor NOPNITHI-NIX-RS-v4 peer-group
neighbor NOPNITHI-NIX-RS-v4 remote-as 555
neighbor NOPNITHI-NIX-RS-v4 description NOPNITHI-NIX-RS-IPv4
neighbor 100.1.1.100 remote-as 555
neighbor 100.1.1.100 peer-group NOPNITHI-NIX-RS-v4
neighbor 100.1.1.100 description Route-Server
!
address-family ipv4
network 2.2.2.0 mask 255.255.255.0
network 22.22.0.0 mask 255.255.0.0
neighbor NOPNITHI-NIX-RS-v4 send-community both
neighbor NOPNITHI-NIX-RS-v4 next-hop-self
neighbor NOPNITHI-NIX-RS-v4 remove-private-as
neighbor NOPNITHI-NIX-RS-v4 maximum-prefix 10000
neighbor 100.1.1.100 activate
exit-address-family

เช็ค Status ว่าทุกอย่างทำงานได้ปกติดี

เช็ค BGP Neighbor Status บน Router Server

bird> show protocols
name proto table state since info
device1 Device master up 12:11:41
AS1x1 BGP master up 12:49:17 Established
AS2x1 BGP master up 12:49:23 Established

หรือถ้าอยากดู route ที่ learn มาจาก BGP

bird> show route
1.1.1.0/24 via 100.1.1.1 on ens3 [AS1x1 12:49:17] * (100) [AS1i]
2.2.2.0/24 via 100.1.1.2 on ens3 [AS2x1 12:49:23] * (100) [AS2i]
11.11.0.0/16 via 100.1.1.1 on ens3 [AS1x1 12:49:17] * (100) [AS1i]
22.22.0.0/16 via 100.1.1.2 on ens3 [AS2x1 12:49:23] * (100) [AS2i]

เช็ค BGP Neighbor Status และ Route บน ISP 1

ISP1#show ip bgp summary
BGP router identifier 11.11.11.11, local AS number 1
BGP table version is 5, main routing table version 5
4 network entries using 576 bytes of memory
4 path entries using 336 bytes of memory
2/2 BGP path/bestpath attribute entries using 320 bytes of memory
1 BGP AS-PATH entries using 24 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 1256 total bytes of memory
BGP activity 4/0 prefixes, 4/0 paths, scan interval 60 secs
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
100.1.1.100 4 555 4 5 3 0 0 00:00:20 2

จะเห็นว่า ISP 1 มี neighbor เป็น route server (100.1.1.100) แล้ว และได้รับ prefix มาจำนวน 2 อัน

ISP1#show ip bgp
BGP table version is 5, local router ID is 11.11.11.11
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
x best-external, a additional-path, c RIB-compressed,
t secondary path,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 1.1.1.0/24 0.0.0.0 0 32768 i
*> 2.2.2.0/24 100.1.1.2 0 0 2 i
*> 11.11.0.0/16 0.0.0.0 0 32768 i
*> 22.22.0.0/16 100.1.1.2 0 0 2 i

ซึ่ง prefix ทั้งสองนั้นก็คือ 2.2.2.2/24 กับ 22.22.22.22/16 ของ ISP 2 นั่นเอง

เช็ค BGP Neighbor Status และ Route บน ISP 2

ISP2#show ip bgp summary
BGP router identifier 22.22.22.22, local AS number 2
BGP table version is 5, main routing table version 5
4 network entries using 576 bytes of memory
4 path entries using 336 bytes of memory
2/2 BGP path/bestpath attribute entries using 320 bytes of memory
1 BGP AS-PATH entries using 24 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 1256 total bytes of memory
BGP activity 4/0 prefixes, 4/0 paths, scan interval 60 secs
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
100.1.1.100 4 555 4 5 5 0 0 00:00:45 2

และ

ISP2#show ip bgp
BGP table version is 5, local router ID is 22.22.22.22
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
x best-external, a additional-path, c RIB-compressed,
t secondary path,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 1.1.1.0/24 100.1.1.1 0 0 1 i
*> 2.2.2.0/24 0.0.0.0 0 32768 i
*> 11.11.0.0/16 100.1.1.1 0 0 1 i
*> 22.22.0.0/16 0.0.0.0 0 32768 i

สรุปจะเห็นว่า ISP 1 และ ISP 2 ต่างก็ได้รับ route ของกันและกันผ่านทาง route server ซึ่งเป็นตัวกลางในการทำ BGP peering และถ้าสังเกตดูจะเห็นว่า IP next hop ของ route เหล่านั้นเป็น IP ของ interface ฝั่งตรงข้ามที่อยู่ใน L2 domain เดียวกันด้วย ดังนั้น traffic วิ่งหากันโดยตรงแน่นอนโดยไม่ต้องทำการ routing

ทดสอบ Ping ระหว่าง ISP 1 ไปยัง ISP 2

ISP1#ping 2.2.2.2 source 1.1.1.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 2.2.2.2, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/1 ms

หรือจะเป็นยังไงก็ได้ระหว่าง network ทั้ง 4 prefix นี้ก็ได้หมดครับ

ISP1#ping 22.22.22.22 source 11.11.11.11
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 22.22.22.22, timeout is 2 seconds:
Packet sent with a source address of 11.11.11.11
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/1 ms

ข้อสรุป (Conclusion)

ทั้งหมดนี้คือ concept เบื้องต้นของ Layer 2 Internet Exchange Point (IXP) ครับ แต่สำหรับใน production จริง ๆ แล้วยังมีอีกหลายเรื่องที่ต้องคำนึงถึงอีกมากมาย

ไม่ว่าจะเป็นเรื่อง high availability ของ switch และ route server, BGP community, เรื่องการจัดการ environment ของ IXP, เรื่อง traffic monitoring รวมถึงเรื่อง security ด้วย

— — — — — — — — — — — — — — —
สารบัญเนื้อหาทั้งหมด (My Contents)
— — — — — — — — — — — — — — —

--

--

Nopnithi Khaokaew (Game)
Nopnithi Khaokaew (Game)

Written by Nopnithi Khaokaew (Game)

Cloud Solutions Architect & Hobbyist Developer | 6x AWS Certified, CKA, CKAD, 2x HashiCorp Certified (Terraform, Vault), etc.

No responses yet