Networking (4) Virtual bridge
Ở bài trước, mình đã tìm hiểu về network namepsace
và virtual ethernet
, hôm nay mình sẽ tiếp tục tìm hiểu về một thiết bị mạng ảo quan trọng khác, đó là bridge
.
Bridge
Bridge
là một thiết bị mạng ảo (virtual network device), cũng giống như veth
mình đã tìm hiểu ở bài trước, mặc định, bridge
hoạt động ở layer 2 (mô hình OSI), và có chức năng tương tự như một switch (kết nối các máy tính ở cùng mạng LAN). Tuy nhiên, khi được gán cho địa chỉ IP, nó cũng có thể hoạt động ở layer 3.
Bridge
kết nối vào network protocol stack
(mình sẽ dùng NPS
để chỉ cụm từ này trong xuyên suốt bài viết) và giống như switch, nó có các cổng để các thiết bị mạng ảo khác có thể kết nối vào như veth
, tap
,...
Trong linux, chúng ta có thể dùng lệnh ip
để tương tác với các thiết bị mạng ảo, hãy cùng tạo ra mô hình như ảnh trên.
ip link add br0 type bridge
ip link set br0 up
ip link add veth0 type veth peer name veth1
ip addr add 20.1.0.10/24 dev veth0
ip addr add 20.1.0.11/24 dev veth1
ip link set veth0 up
ip link set veth1 up
ip link set dev veth0 master br0
# verify result
bridge link
brctl show
Kết quả có được sau khi chạy các câu lệnh trên:
# bridge link
6: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 2
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.8e5ec2c9742a no veth0
Ở bài viết về veth, sau khi tạo 2 virtual ethernet thì veth0
sẽ có 1 đầu kết nối với NPS
và đây là một giao tiếp 2 chiều. Ở mô hình trên, mình kết nối veth0
vào br0
, vậy hãy xem thử có gì điều khác nhau bằng lệnh ping
(lưu ý để arp protocol
có thể hoạt động thì bạn phải cấu hình network như ở bài veth).
ping -c 1 -I veth0 20.1.0.11
Sử dụng tcpdump
để bắt gói tin trên tất cả network interface
:
tcpdump -n -i any
Kết quả của lệnh ping
và tcpdump
như sau:
# ping
PING 20.1.0.11 (20.1.0.11) from 20.1.0.10 veth0: 56(84) bytes of data.
From 20.1.0.10 icmp_seq=1 Destination Host Unreachable
--- 20.1.0.11 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
# tcpdump
11:05:40.901664 veth0 Out ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
11:05:40.901671 veth1 B ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
11:05:40.901697 veth1 Out ARP, Reply 20.1.0.11 is-at de:9a:36:c3:48:93, length 28
11:05:40.901698 veth0 In ARP, Reply 20.1.0.11 is-at de:9a:36:c3:48:93, length 28
11:05:40.901698 br0 In ARP, Reply 20.1.0.11 is-at de:9a:36:c3:48:93, length 28
Lần này, gói tin ARP
được gửi đi từ veth0
tới veth1
và có phản hồi, tuy nhiên thay vì gói tin phản hồi đi trở lại NPS
thì nó đi vào br0
, kết quả là NPS
không lấy được địa chỉ MAC của veth1
để cập nhật bảng mapping MAC address - IP address
cho veth0
, mà thông tin này sẽ được cập nhật ở br0
, sử dụng lệnh arp -n
và brctl showmacs br0
để kiểm chứng lại và nhận được kết quả:
# arp -n
Address HWtype HWaddress Flags Mask Iface
172.17.0.2 ether 02:42:ac:11:00:02 C eth0
20.1.0.11 (incomplete) veth0
172.17.0.1 ether 02:42:9e:e4:b1:d5 C eth0
20.1.0.10 ether 8e:5e:c2:c9:74:2a C veth1
# brctl showmacs br0 -> mac address de:9a:36:c3:48:93 của veth1
port no mac addr is local? ageing timer
1 8e:5e:c2:c9:74:2a yes 0.00
1 8e:5e:c2:c9:74:2a yes 0.00
1 de:9a:36:c3:48:93 no 3.38
Để thực hiện được lệnh ping
ở trên thông qua br0
, ta phải gán địa chỉ ip
cho br0
thay vì veth0
, lúc này br0
sẽ có thêm vai trò routing thay vì chỉ đơn thuần là một virtual switch.
ip addr del 20.1.0.10/24 dev veth0
ip addr add 20.1.0.10/24 dev br0
Chạy lại lệnh ping
và tcpdump
:
ping -c 1 -I br0 20.1.0.11
Ta được kết quả:
# ping
PING 20.1.0.11 (20.1.0.11) from 20.1.0.10 br0: 56(84) bytes of data.
64 bytes from 20.1.0.11: icmp_seq=1 ttl=64 time=0.717 ms
--- 20.1.0.11 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.717/0.717/0.717/0.000 ms
# tcpdump
12:00:17.086571 br0 Out ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
12:00:17.086611 veth0 Out ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
12:00:17.086616 veth1 B ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
12:00:17.086865 veth1 Out ARP, Reply 20.1.0.11 is-at de:9a:36:c3:48:93, length 28
12:00:17.086867 veth0 In ARP, Reply 20.1.0.11 is-at de:9a:36:c3:48:93, length 28
12:00:17.086867 br0 In ARP, Reply 20.1.0.11 is-at de:9a:36:c3:48:93, length 28
12:00:17.086944 br0 Out IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 106, seq 1, length 64
12:00:17.086947 veth0 Out IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 106, seq 1, length 64
12:00:17.086948 veth1 In IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 106, seq 1, length 64
12:00:17.087104 lo In IP 20.1.0.11 > 20.1.0.10: ICMP echo reply, id 106, seq 1, length 64
NPS
nhận được ARP reply
và nếu sử dụng arp -n
để xem lại kết quả, chúng ta sẽ thấy bản ghi của veth1
ở br0
:
Address HWtype HWaddress Flags Mask Iface
20.1.0.11 ether de:9a:36:c3:48:93 C br0
172.17.0.1 ether 02:42:9e:e4:b1:d5 C eth0
20.1.0.10 ether 8e:5e:c2:c9:74:2a C veth1
Hãy quay lại ví dụ lúc mà mình chưa thiết lập địa chỉ IP cho br0
, nó sẽ là một thiết bị hoạt động đơn thuần ở layer 2
với các ethernet frame
, không có sự liên kết trực tiếp đến NPS
(layer 3
) thông qua routing, nên lúc này các kết nối đến máy chủ vật lý bằng địa chỉ IP thông qua virtual bridge
là không thể xảy ra.
Ứng dụng
Virtual machine
Mô hình network cơ bản của VM đó là các NIC trong VM sẽ kết nối với tun/tap
device và đi qua br0
, lúc này br0
đóng vai trò như 1 switch layer 2
. Nếu muốn VM giao tiếp được với máy chủ, chúng ta phải cấu hình thêm địa chỉ IP cho br0
và nó sẽ có thêm vai trò là 1 gateway
.
Docker container
Bridge
được sử dụng như driver mặc định trong docker, cung cấp sự giao tiếp cho các container chạy trên cùng 1 máy chủ vật lý, mô hình hoạt động như sau:
Ở bài viết tiếp theo mình sẽ phân tích chi tiết hơn về mô hình này và cách docker dùng port forwarding
bằng iptables
.
Tổng kết
Bài viết này mình đã tìm hiểu qua một thiết bị mạng ảo quan trọng đó là bridge
, cách nó hoạt động ở layer 2
và layer 3
cũng như một số ứng dụng trong thực tế.