Linux網絡設置高級指南
本文面向的是被Linux復雜的有線無線網絡架構弄得頭昏腦脹;或者被網上半吊子的教程弄得暈頭轉向;或者厭倦了Network Manager之類圖形界面無窮盡的BUG(很多抄襲的是Windows,畫虎不成反類貓,在一些概念上就存在錯誤);或者想要了解一些技術細節的,像一樣我渴望獲得完全駕馭的能力而不是隔靴搔癢的人。
本文需要一定的計算機網絡和Linux基礎,其中的大部分內容很新,基於2.6內核之後的新架構。
Linux不同發行版的軟件包名稱、配置文件的命名和位置都不盡相同,本文基於的是Debian/Ubuntu系統,很多內容參考了Debian Reference的第5章。
當然,本文依舊有很多不足之處,例如沒有深入到Linux內核機制中去,這就需要以後進一步完善了。
靜態設置
靜態設置的意思是所有配置都寫在配置文件中,由操作系統自動進行設置。
靜態設置依賴udev、ifupdown、isc-dhcp-client、resolvconf、wireless-tools、wpasupplicant等軟件包。
首先,網絡的正常運行依賴於硬件設備。在系統引導或者熱插拔的時候,內核通過udev將網絡設備映射到用戶空間的sysfs虛擬文件系統。例如:
root@X230:/sys/class/net# ls -l
總用量 0
lrwxrwxrwx 1 root root 0 7月 4 15:01 eth0 -> ../../devices/pci0000:00/0000:00:19.0/net/eth0
lrwxrwxrwx 1 root root 0 7月 4 15:00 lo -> ../../devices/virtual/net/lo
lrwxrwxrwx 1 root root 0 7月 4 15:01 wlan0 -> ../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0
可以看到,系統當前存在三個網絡設備:lo為回環設備;eth0為有線網卡;wlan0為無線網卡。遵循Unix“一切皆文件”的思想,其它工具都是直接或者間接地修改這些虛擬文件來達到設置目的的。
/etc/network/interfaces文件記錄了所有的靜態配置信息。內核在引導的時候,會自動啟動標志為“auto”的設備,例如:
auto lo
auto eth0
auto wlan0
而如果設備標志為“allow-hotplug”,那麼內核在檢測到熱插拔事件的時候,也會自動啟動。例如:
allow-hotplug lo
allow-hotplug eth0
allow-hotplug wlan0
因為回環設備始終應該是存在的,所以/etc/network/interfaces文件的內容至少是:
auto lo
iface lo inet loopback
內核啟動網絡設備調用的是ifupdown工具,而ifupdown工具也是依賴於/etc/network/interfaces配置文件的。
對於有線(Wired)設備,物理層和數據鏈路層無須操作系統干預,網卡根據CSMA/CD協議就能夠自行設置,所以/etc/network/interfaces文件只需包含網絡層以上的配置信息,例如IP地址、子網掩碼、默認網關等。例如:
iface eth0 inet static
address 192.168.11.100
netmask 255.255.255.0
gateway 192.168.11.1
“默認網關”其實是路由的概念,在這裡作為設備的一個屬性,和IP地址子網掩碼放在一起我覺得很不妥,很容易誤導初學者,尤其是存在多網卡多IP地址的情況。
對於DNS,首先需要注意的是它屬於應用層協議,和網絡設備以及網絡層並無直接聯系。傳統上Linux的DNS配置文件為/etc/resolv.conf,一行一個服務器IP地址。例如:
nameserver 218.2.135.1
nameserver 61.147.37.1
如果安裝了resolvconf工具,那麼DNS的配置會被接管,此時/etc/resolv.conf就變成了一個符號鏈接,鏈接到了resolvconf運行時候動態維護的一個文件。在這種情況下,DNS的配置也可以寫到/etc/network/interfaces文件中了,例如:
iface eth0 inet static
address 192.168.11.100
netmask 255.255.255.0
gateway 192.168.11.1
dns-nameservers 218.2.135.1 61.147.37.1
ifupdown工具會自動調用resolvconf完成DNS設置。
此處我也甚覺不妥,因為上面講過,DNS是應用層的概念,這樣寫的話讓初學者覺得好像DNS是網絡設備的屬性一樣(傳統Linux還真是有很多不足之處)。
如果安裝了isc-dhcp-client工具,那麼/etc/network/interfaces文件中就可以直接配置DHCP,例如:
iface eth0 inet dhcp
isc-dhcp-client有自己的配置文件,可以控制從DHCP服務器上獲取哪些信息(例如DNS服務器地址)。
ifupdown工具會自動調用isc-dhcp-client完成DHCP設置。
此處需要注意的是:不論resolvconf是否存在,dhclient均會直接修改/etc/resolv.conf文件(不管它是不是一個鏈接),不過一般情況下也沒有什麼問題。
對於無線(Wireless)設備,工作方式和有線設備有很大的不同(不是插上網線就能直接用的)。數據鏈路層的連接必須由操作系統協同完成,例如連接哪個SSID、使用哪條信道、采用什麼認證方式(WEP、WPA...)。這些鏈路層配置信息也可以寫到/etc/network/interfaces文件中以供ifupdown工具使用。
iface ath0 inet dhcp
wpa-ssid homezone
wpa-psk 密碼
ifupdown工具會自動調用wpasupplicant完成WPA設置。
例如WEP的配置:
iface eth0 inet dhcp
wireless-essid Home
wireless-key1 0123-4567-89ab-cdef
wireless-key2 12345678
wireless-key3 s:password
wireless-defaultkey 2
wireless-keymode open
ifupdown工具會自動調用wireless-tools完成WEP設置。
准靜態設置
靜態設置適合於網絡環境固定的情況,例如服務器、辦公室電腦等。如果網絡環境經常有變動,但是變動都是已知的,那麼可以在/etc/network/interfaces文件中寫入不固定的網絡配置,這些配置不對應到具體的硬件設備名,例如:
iface config1 inet dhcp
iface config2 inet static
address 192.168.11.100
netmask 255.255.255.0
gateway 192.168.11.1
dns-domain example.com
dns-nameservers 192.168.11.1
可以手工運行ifupdown工具切換配置,例如將eth0切換到config1:
ifup eth0=config1
將eth0切換到config2:
ifdown eth0=config1
ifup eth0=config2
動態設置
如果網絡環境經常變動而且是未知的,或者為了使用腳本等自動化工具達到完全駕馭網絡的能力,那麼靜態和准靜態設置就捉襟見肘了。
動態設置依賴iproute、isc-dhcp-client、wireless-tools、wpasupplicant等軟件包,直接使用命令行,以達到最大的靈活性。
首先,/etc/network/interfaces文件僅保留回環設備lo的配置信息:
auto lo
iface lo inet loopback
iproute替代了過時的net-tools等工具(ifconfig)。
通過“ip link”命令可以查詢到當前所有網絡設備的狀態和參數,例如:
root@X230:~# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 3c:97:0e:6d:e9:7c brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 84:3a:4b:5b:7b:c8 brd ff:ff:ff:ff:ff:ff
可以看到當前eth0和wlan0設備都是處於關閉狀態(這是顯然的,因為/etc/network/interfaces文件中已經沒有它們的配置信息了)。
使用“ip link set 設備名 up”命令可以啟動設備,使用“ip link set 設備名 down”命令可以關閉設備。
對於有線(Wired)設備,上面講過,無須做額外設置,鏈路層就可以正常工作了。
對於無線(Wireless)設備,需要使用wireless-tools、wpasupplicant完成鏈路層的連接。
例如掃描當前可用都無線連接,可以使用wavemon工具,或者使用“iwlist scan”命令。
例如連接Ad-Hoc。雙方的essid、channel、cell(也就是iwconfig中的ap)均必須一致。雙方創建連接誰先誰後都沒有關系。例如:
iwconfig wlan0 mode ad-hoc essid test channel 7 ap 0E:0E:0A:3A:10:3B key off
以上命令即刻生效。
例如連接WEP認證的無線網絡:
iwconfig wlan0 essid "myhome" key 0123-4567-89
如果要連接WPA認證的無線網絡,wireless-tools就無可奈何了,必須使用wpasupplicant。
wpasupplicant並不是像wireless-tools一樣簡單地用命令行配一配就可以了,它必須先啟動一個服務進程,然後使用另外一個命令行工具對服務進程進行設置,而且在WIFI連接期間該服務進程必須始終運行著。
為什麼不和wireless-tools做在一起呢?真怪異,真惡心!
服務進程可以以後台方式啟動,也可以以前台方式啟動。
後台方式:
wpa_supplicant -i wlan0 -D nl80211,wext -s -B -P /var/run/wpa_supplicant.wlan0.pid -C /var/run/wpa_supplicant
其中:-i指定設備名;-D指定認證協議;-s -B指定在後台運行,並且調試輸出到syslog中;-C參數指定“ctrl_interface”的位置,注意,wpa_supplicant是可以有配置文件的,而且配置文件中可以記錄WIFI的靜態配置,類似於/etc/network/interfaces的功能,但是我們這裡用不到,在沒有配置文件的情況下,“ctrl_interface”是必不可少的,wpa_cli通過它與之交互。
前台方式:
wpa_supplicant -i wlan0 -D nl80211,wext -dd -P /var/run/wpa_supplicant.wlan0.pid -C /var/run/wpa_supplicant
其中,-dd表示輸出更詳細的調試信息。
然後使用wpa_cli進行設置。wpa_cli可以工作在交互模式,也可以命令行模式。例如在交互模式下執行如下命令加入並啟用網絡:
> add_network
0
> set_network 0 ssid "ChinaUnicom-Me"
OK
> set_network 0 key_mgmt WPA-PSK
OK
> set_network 0 psk "密碼"
OK
> enable_network 0
OK
到上面為止,無論是有線網絡還是無線網絡,鏈路層已經連通了。下面就要使用iproute等工具進行網絡層的設置。
如果要設置DHCP,很簡單。例如:
dhclient wlan0 -r
dhclient wlan0
如果要手工設置地址,那麼,例如:
ip address add 192.168.1.3/24 dev wlan0
ip route add default via 192.168.1.1 dev wlan0
第一行增加IP地址,第二行設置默認路由。
最後,使用文本編輯器或者腳本修改/etc/resolv.conf的DNS設置,例如:
echo nameserver 221.6.4.66 > /etc/resolv.conf
搞定,可以使用iwconfig和ifconfig查看當前設置。例如:
iwconfig wlan0 && ifconfig wlan0
現在,寫腳本就游刃有余了,例如下面就是我的筆記本電腦在家裡的設置腳本:
#!/bin/sh
echo 清理工作
sudo killall wpa_supplicant
sudo ip link set eth0 down
sudo ip link set wlan0 down
sudo ip addr flush eth0
sudo ip addr flush wlan0
echo 啟用wlan0
sudo ip link set wlan0 up
echo 鏈路層連接
sudo wpa_supplicant -i wlan0 -D nl80211,wext -s -B -P /var/run/wpa_supplicant.wlan0.pid -C /var/run/wpa_supplicant
sudo wpa_cli add_network
# 注意單引號套雙引號
sudo wpa_cli set_network 0 ssid '"ChinaUnicom-Me"'
sudo wpa_cli set_network 0 key_mgmt WPA-PSK
sudo wpa_cli set_network 0 psk '"........"'
sudo wpa_cli enable_network 0
echo 網絡層設置:IP地址和默認路由
sudo ip addr add 192.168.1.3/24 dev wlan0
sudo ip route add default via 192.168.1.1 dev wlan0
echo DNS設置
# 此處不能使用>符號,否則權限不夠
sudo echo nameserver 221.6.4.66 | sudo tee /etc/resolv.conf