原文鏈接:http://int32bit.me/2016/05/04/Linux常用網絡工具總結/
本文整理了在實踐過程中使用的Linux網絡工具,這些工具提供的功能非常強大,我們平時使用的只是冰山一角,比如lsof
、ip
、tcpdump
、iptables
等。本文不會深入研究這些命令的強大用法,因爲每個命令都足以寫一篇文章,本文只是簡單地介紹並輔以幾個簡單demo實例,旨在大腦中留個印象,平時遇到問題時能夠快速搜索出這些工具,利用強大的man
工具,提供一定的思路解決問題。
ping
使用這個命令判斷網絡的連通性以及網速,偶爾還順帶當做域名解析使用(查看域名的IP):
ping google.com
默認使用該命令會一直髮送ICMP包直到用戶手動中止,可以使用-c
命令指定發送數據包的個數,使用-W
指定最長等待時間,如果有多張網卡,還可以通過-I
指定發送包的網卡。
小技巧: 在ping過程中按下ctrl+|
會打印出當前的summary信息,統計當前發送包數量、接收數量、丟包率等。
其他比如-b
發送廣播,另外注意ping只能使用ipv4,如果需要使用ipv6,可以使用ping6
命令。
netstat
這個命令用來查看當前建立的網絡連接(深刻理解netstat每一項代表的含義)。最經典的案例就是查看本地系統打開了哪些端口:
fgp@controller:~$ sudo netstat -lnpt
[sudo] password for fgp:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 2183/mysqld
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 2506/memcached
tcp 0 0 0.0.0.0:9292 0.0.0.0:* LISTEN 1345/python
tcp 0 0 0.0.0.0:6800 0.0.0.0:* LISTEN 2185/ceph-osd
tcp 0 0 0.0.0.0:6801 0.0.0.0:* LISTEN 2185/ceph-osd
tcp 0 0 0.0.0.0:28017 0.0.0.0:* LISTEN 1339/mongod
tcp 0 0 0.0.0.0:6802 0.0.0.0:* LISTEN 2185/ceph-osd
tcp 0 0 0.0.0.0:6803 0.0.0.0:* LISTEN 2185/ceph-osd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1290/sshd
netstat能夠查看所有的網絡連接,包括unix socket連接,其功能非常強大。
另外使用netstat還可以查看本地路由表:
fgp@controller:~$ sudo netstat -nr
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 brqcb225471-1f
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 brqcb225471-1f
192.168.56.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
以上Genmask
爲0.0.0.0
的表示默認路由,即連接外網的路由。網絡中0.0.0.0的IP地址表示整個網絡,即網絡中的所有主機。它的作用是幫助路由器發送路由表中無法查詢的包。如果設置了全零網絡的路由,路由表中無法查詢的包都將送到全零網絡的路由中去。
lsof
lsof
命令用來查看打開的文件(list open files),由於在Linux中一切皆文件,那socket、pipe等也是文件,因此能夠查看網絡連接以及網絡設備,其中和網絡最相關的是-i
選項,它輸出符合條件的進程(4、6、協議、:端口、 @ip等),它的格式爲[46][protocol][@hostname|hostaddr][:service|port]
,比如查看22端口有沒有打開,哪個進程打開的:
fgp@controller:~$ sudo lsof -i :22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1290 root 3u IPv4 10300 0t0 TCP *:ssh (LISTEN)
sshd 1290 root 4u IPv6 10302 0t0 TCP *:ssh (LISTEN)
可見22端口是sshd這個命令,其進程號pid爲1290打開的。
可以指定多個條件,但默認是OR關係的,如果需要AND關係,必須傳入-a
參數,比如查看22端口並且使用Ipv6連接的進程:
fgp@controller:~$ sudo lsof -c sshd -i 6 -a -i :22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1290 root 4u IPv6 10302 0t0 TCP *:ssh (LISTEN)
列出所有與192.168.56.1
(我的宿主機IP地址)的ipv4連接:
fgp@controller:~$ sudo lsof -i [email protected]
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 2299 root 3u IPv4 14047 0t0 TCP controller:ssh->mac:54558 (ESTABLISHED)
sshd 2377 fgp 3u IPv4 14047 0t0 TCP controller:ssh->mac:54558 (ESTABLISHED)
iftop
用過top
以及iotop
的,自然能夠大致猜到iftop
的功能,它是用於查看網絡流量的工具(display bandwidth usage on an interface by host):
sudo iftop
nc
nc(netcat)被稱爲網絡工具的瑞士軍刀,其非常輕巧但功能強大!常常作爲網絡應用的Debug分析器,可以根據需要創建各種不同類型的網絡連接。官方描述的功能包括:
- simple TCP proxies
- shell-script based HTTP clients and servers
- network daemon testing
- a SOCKS or HTTP ProxyCommand for ssh(1)
- and much, much more
總之非常強大,能夠實現簡單的聊天工具、模擬ssh登錄遠程主機、遠程傳輸文件等。一個經典的用法是端口掃描。比如我要掃描192.168.56.2
主機1~100
端口,探測哪些端口開放的(黑客攻擊必備):
fgp@controller:~$ nc -zv 192.168.56.2 1-100 |& grep 'succeeded!'
Connection to 192.168.56.2 22 port [tcp/ssh] succeeded!
Connection to 192.168.56.2 80 port [tcp/http] succeeded!
從結果中發現,該主機打開了22
和80
端口。
tcpdump
tcpdump
(dump traffic on a network)是一個強大的命令行抓包工具,千萬不要被它的名稱誤導以爲只能抓取tcp包,它能抓任何協議的包。它能夠實現Wireshark
一樣的功能,並且更加靈活自由!比如需要抓取目標主機是192.168.56.1
,通過端口22
的傳輸數據包:
sudo tcpdump -n -i eth1 'dst host 192.168.56.1 && port 22'
輸出爲:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
23:57:39.507490 IP 192.168.56.2.22 > 192.168.56.1.54558: Flags [P.], seq 3010719012:3010719120, ack 1116715283, win 354, options [nop,nop,TS val 1049052 ecr 187891473], length 108
23:57:39.507607 IP 192.168.56.2.22 > 192.168.56.1.54558: Flags [P.], seq 108:144, ack 1, win 354, options [nop,nop,TS val 1049052 ecr 187891473], length 36
23:57:39.507784 IP 192.168.56.2.22 > 192.168.56.1.54558: Flags [P.], seq 144:252, ack 1, win 354, options [nop,nop,TS val 1049052 ecr 187891476], length 108
抓取HTTP
包:
sudo tcpdump -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854
其中0x4745
爲"GET"
前兩個字母"GE"
,0x4854
爲"HTTP"
前兩個字母"HT"
。
指定-A
以ACII碼輸出數據包,使用-c
指定抓取包的個數。
telnet
telnet協議客戶端(user interface to the TELNET protocol),不過其功能並不僅僅限於telnet協議,有時也用來探測端口,比如查看本地端口22是否開放:
fgp@controller:~$ telnet localhost 22
Trying ::1...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.6
可見成功連接到localhost
的22
端口,說明端口已經打開,還輸出了banner
信息。
ifconfig
ifconfig也是熟悉的網卡配置工具(configure a network interface),我們經常使用它來查看網卡信息(比如IP地址、發送包的個數、接收包的個數、丟包個數等)以及配置網卡(開啓關閉網卡、修改網絡mtu、修改ip地址等)。
查看網卡ip地址:
fgp@controller:~$ ifconfig eth0
eth0 Link encap:Ethernet HWaddr 08:00:27:c9:b4:f2
inet6 addr: fe80::a00:27ff:fec9:b4f2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:27757 errors:0 dropped:0 overruns:0 frame:0
TX packets:589 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:10519777 (10.5 MB) TX bytes:83959 (83.9 KB)
爲網卡eth0增加一個新的地址(虛擬網卡):
fgp@controller:~$ sudo ifconfig eth0:0 10.103.240.2/24
fgp@controller:~$ ifconfig eth0:0
eth0:0 Link encap:Ethernet HWaddr 08:00:27:c9:b4:f2
inet addr:10.103.240.2 Bcast:10.103.240.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
關閉網卡以及開啓網卡:
sudo ifconfig eth0 down
sudo ifconfig eth0 up
nslookup & dig
nslookup用於交互式域名解析(query Internet name servers interactively),當然也可以直接傳入域名作爲Ad-Hoc命令使用,比如查看google.com的ip地址:
fgp@controller:~$ nslookup google.com
Server: 114.114.114.114
Address: 114.114.114.114#53
Non-authoritative answer:
Name: google.com
Address: 37.61.54.158
查看使用的DNS服務器地址:
fgp@controller:~$ nslookup
> server
Default server: 114.114.114.114
Address: 114.114.114.114#53
Default server: 8.8.8.8
Address: 8.8.8.8#53
dig命令也是域名解析工具(DNS lookup utility),不過提供的信息更全面:
fgp@controller:~$ dig google.com
; <<>> DiG 9.9.5-3ubuntu0.8-Ubuntu <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53828
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 4
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 2730 IN A 37.61.54.158
;; AUTHORITY SECTION:
google.com. 10204 IN NS ns2.google.com.
google.com. 10204 IN NS ns4.google.com.
google.com. 10204 IN NS ns3.google.com.
google.com. 10204 IN NS ns1.google.com.
;; ADDITIONAL SECTION:
ns1.google.com. 86392 IN A 216.239.32.10
ns2.google.com. 80495 IN A 216.239.34.10
ns3.google.com. 85830 IN A 216.239.36.10
ns4.google.com. 13759 IN A 216.239.38.10
;; Query time: 17 msec
;; SERVER: 114.114.114.114#53(114.114.114.114)
;; WHEN: Thu May 05 00:11:48 CST 2016
;; MSG SIZE rcvd: 180
whois
whois用於查看域名所有者的信息(client for the whois directory service),比如註冊郵箱、手機號碼、域名服務商等:
fgp@controller:~$ whois coolshell.cn
Domain Name: coolshell.cn
ROID: 20090825s10001s91994755-cn
Domain Status: ok
Registrant ID: hc401628324-cn
Registrant: 陳皓
Registrant Contact Email: [email protected]
Sponsoring Registrar: 阿里雲計算有限公司(萬網)
Name Server: f1g1ns1.dnspod.net
Name Server: f1g1ns2.dnspod.net
Registration Time: 2009-08-25 00:40:26
Expiration Time: 2020-08-25 00:40:26
DNSSEC: unsigned
我們發現coolshell.cn
這個域名是陳皓在萬網購買註冊的,註冊時間是2009年,註冊郵箱是[email protected]
。
route
route命令用於查看和修改路由表:
查看路由表:
fgp@controller:~$ sudo route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 brqcb225471-1f
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 brqcb225471-1f
192.168.56.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
增加/刪除路由分別爲add
/del
子命令,比如刪除默認路由:
sudo route del default
增加默認路由,網關爲192.168.1.1,網卡爲brqcb225471-1f:
sudo route add default gw 192.168.1.1 dev brqcb225471-1f
ip
ip命令可以說是無比強大了,它完全可以替換ifconfig
、netstat
、route
、arp
等命令,比如查看網卡eth1 IP地址:
[] 內的內容意思是:可寫可不寫
如果是{},那就必須要在{}內給出的選擇裏選一個。
fgp@controller:~$ sudo ip addr ls dev eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:9a:d5:d1 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.2/24 brd 192.168.56.255 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe9a:d5d1/64 scope link
valid_lft forever preferred_lft forever
查看網卡eth1配置:
fgp@controller:~$ sudo ip link ls eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:9a:d5:d1 brd ff:ff:ff:ff:ff:ff
查看路由:
fgp@controller:~$ ip route
default via 192.168.1.1 dev brqcb225471-1f
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.1.0/24 dev brqcb225471-1f proto kernel scope link src 192.168.1.105
192.168.56.0/24 dev eth1 proto kernel scope link src 192.168.56.2
查看arp信息:
fgp@controller:~$ sudo ip neigh
192.168.56.1 dev eth1 lladdr 0a:00:27:00:00:00 REACHABLE
192.168.0.6 dev vxlan-80 lladdr fa:16:3e:e1:30:c8 PERMANENT
172.17.0.2 dev docker0 lladdr 02:42:ac:11:00:02 STALE
192.168.56.3 dev eth1 FAILED
192.168.1.1 dev brqcb225471-1f lladdr 30:fc:68:41:12:c6 STALE
查看網絡命名空間:
fgp@controller:~$ sudo ip netns ls
qrouter-24bf83c7-f61d-496b-8115-09f0f3d64d21
qdhcp-9284d7a8-711a-4927-8a10-605b34372768
qdhcp-cb225471-1f85-4771-b24b-a4a7108d93a4
進入某個網絡命名空間:
fgp@controller:~$ sudo ip netns exec qrouter-24bf83c7-f61d-496b-8115-09f0f3d64d21 bash
root@controller:~# ifconfig
qg-0d258e6d-83 Link encap:Ethernet HWaddr fa:16:3e:93:6f:a3
inet addr:172.16.1.101 Bcast:172.16.1.255 Mask:255.255.255.0
inet6 addr: fe80::f816:3eff:fe93:6fa3/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1035 errors:0 dropped:0 overruns:0 frame:0
TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:102505 (102.5 KB) TX bytes:1200 (1.2 KB)
brctl
brctl
是linux網橋管理工具,可用於查看網橋、創建網橋、把網卡加入網橋等。
查看網橋:
fgp@controller:~$ sudo brctl show
bridge name bridge id STP enabled interfaces
brq9284d7a8-71 8000.12841adee45f no tap36daf550-27
tape729e013-df
vxlan-80
brqcb225471-1f 8000.080027c9b4f2 no eth0
tap0d258e6d-83
tapb844e7a5-83
docker0 8000.0242e4580b61 no veth50ed8dd
以上因爲部署了openstack neutron
以及docker
,因此網橋比較複雜。 其他子命令如addbr
用於創建網橋、delbr
用戶刪除網橋(刪除之前必須處於down狀態,使用ip link set br_name down
)、addif
把網卡加到網橋等。
traceroute
ping命令用於探測兩個主機間連通性以及響應速度,而traceroute會統計到目標主機的每一跳的網絡狀態(print the route packets trace to network host),這個命令常常用於判斷網絡故障,比如本地不通,可使用該命令探測出是哪個路由出問題了。如果網絡很卡,該命令可判斷哪裏是瓶頸:
fgp@controller:~$ sudo traceroute -I -n int32bit.me
traceroute to int32bit.me (192.30.252.154), 30 hops max, 60 byte packets
1 192.168.1.1 4.610 ms 5.623 ms 5.515 ms
2 117.100.96.1 5.449 ms 5.395 ms 5.356 ms
3 124.205.97.48 5.362 ms 5.346 ms 5.331 ms
4 218.241.165.5 5.322 ms 5.310 ms 5.299 ms
5 218.241.165.9 5.187 ms 5.138 ms 7.386 ms
...
可以看到,從主機到int32bit.me
共經過30跳,並統計了每一跳間的響應時間。
另外可以參考tracepath
。
mtr
mtr是常用的網絡診斷工具(a network diagnostic tool),它把ping和traceroute併入一個程序的網絡診斷工具中並實時刷新。
mtr -n int32bit.me
輸出如圖:從圖上可以看出從本地到int32bit.me
經過的所有路由,每一個路由間的丟包率、響應時間等。
ss
ss命令也是一個查看網絡連接的工具(another utility to investigate sockets),用來顯示處於活動狀態的套接字信息。關於ss的描述,引用Linux命令大全-ss命令
ss命令可以用來獲取socket統計信息,它可以顯示和netstat類似的內容。但ss的優勢在於它能夠顯示更多更詳細的有關TCP和連接狀態的信息,而且比netstat更快速更高效。當服務器的socket連接數量變得非常大時,無論是使用netstat命令還是直接cat /proc/net/tcp,執行速度都會很慢。可能你不會有切身的感受,但請相信我,當服務器維持的連接達到上萬個的時候,使用netstat等於浪費 生命,而用ss纔是節省時間。 天下武功唯快不破。ss快的祕訣在於,它利用到了TCP協議棧中tcp_diag。tcp_diag是一個用於分析統計的模塊,可以獲得Linux 內核中第一手的信息,這就確保了ss的快捷高效。當然,如果你的系統中沒有tcp_diag,ss也可以正常運行,只是效率會變得稍慢。
其中比較常用的參數包括:
- -l 查看處於LISTEN狀態的連接
- -t 查看tcp連接
- -4 查看ipv4連接
- -n 不進行域名解析
因此我們可以通過ss
命令查看本地監聽的所有端口(和netstat命令功能類似):
ss -t -l -n -4
輸出如圖:
curl
curl是強大的URL傳輸工具,支持FILE, FTP, HTTP, HTTPS, IMAP, LDAP, POP3,RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET以及TFTP等協議。我們使用這個命令最常用的功能就是通過命令行發送HTTP請求以及下載文件,它幾乎能夠模擬所有瀏覽器的行爲請求,比如模擬refer(從哪個頁面跳轉過來的)、cookie、agent(使用什麼瀏覽器)等等,同時還能夠模擬表單數據。
curl -X POST -d "DDDDD=2013140333&upass=1q2w3e4r&save_me=1&R1=0" 10.3.8.211
以上方法利用curl往認證服務器發送POST請求,發送數據爲用戶名以及密碼(模擬表單輸入)。
具體用法參考buptLogin。
Openstack的命令行工具,比如nova,傳入--debug
參數就會顯示curl
往nova-api的curl REST請求。
curl命令非常強大,掌握了它能夠發揮巨大的作用,其他有用參數列舉如下:
-i
顯示頭部信息-I
只顯示頭部信息,不顯示正文-X
指定請求方法,比如GET、POST等-d
發送數據--form
模擬表單,利用這個參數可以上傳文件、模擬點擊按鈕等-A
指定用戶代理,比如Mozilla/4.0
,有些坑爹網址必須使用IE訪問怎麼辦-b
設置cookie-c
指定cookie文件-e
指定referer,有些網址必須從某個頁面跳轉過去--header
設置請求的頭部信息--user
有些頁面需要HTTP認證, 傳遞name:password
認證
wget
wget是一個強大的非交互網絡下載工具(The non-interactive network downloader),雖然curl也支持文件下載,不過wget更強大,比如支持斷點下載等。
最簡單的用法直接加上文件URL即可:
wget http://xxx/xxx/video.mp4
使用-r
參數爲遞歸的下載網頁,默認遞歸深度爲5,相當於爬蟲,用戶可以通過-l
指定遞歸深度。
注意wget默認沒有開啓斷點下載功能,需要手動傳入-c
參數。
如果需要批量下載,可以把所有的URL寫入文件download.txt,然後通過-i
指定下載文件列表:
wget -i download.txt
如果用戶不指定保存文件名,wget默認會以最後一個符合/的後面的字符作爲保存文件名,有時不是我們所期望的,此時需要-O
指定保存的文件名。
通過--limit-rate
可以限制下載的最大速度。
使用-b
可以實現後臺下載。
另外wget甚至可以鏡像整個網站:
wget --mirror -p --convert-links -P int32bit http://int32bit.me
wget還支持指定下載文件的格式,比如只下載jpg圖片:
wget -A.jpg -r -l 2 http://int32bit.me/
axel
axel是一個多線程下載工具(A light download accelerator for Linux),通過建立多連接,能夠大幅度提高下載速度,所以我經常使用這個命令開掛下載大文件,比wget快多了,並且默認就支持斷點下載:
開啓20個線程下載文件:
axel -n 20 URL
這個強大的下載工具極力推薦,非常好用!
nethogs
我們前面介紹的iftop工具能夠根據主機查看流量(by host),而nethogs則可以根據進程查看流量信息(Net top tool grouping bandwidth per process)。ubuntu14.04中使用apt-get安裝的有bug,需要手動安裝:
sudo apt-get install build-essential libncurses5-dev libpcap-dev
git clone https://github.com/raboof/nethogs
cd nethogs
make -j 4
編譯完後執行
./nethogs eth1
我們指定了監控的網卡爲eth1,結果如圖:
由於eth1是私有ip,只有ssh進程,從圖中我們可以看到它的進程號爲17264,程序爲sshd,共發送了1.593MB數據,接收了607.477MB數據(scp了一個鏡像文件)。按m
鍵還能切換視角查看當前流量。
iptables
iptables是強大的包過濾工具,Docker、Neutron都網絡配置都離不開iptables。iptables通過一系列規則來實現數據包過濾、處理,能夠實現防火牆、NAT等功能。當一個網絡數據包進入到主機之前,先經過Netfilter檢查,即iptables規則,檢查通過則接受(Accept)進入本機資源,否則丟棄該包(Drop)。規則是有順序的,如果匹配第一個規則,則執行該規則的Action,不會執行後續的規則。iptables的規則有多個表構成,每個表又由鏈(chain)構成,每個表的功能不一樣,本文只涉及兩個簡單的表,即Filter表和NAT表,望文生義即可瞭解,Filter表用於包過濾,而NAT表用來進行源地址和目的地址的IP或者端口轉換。
1.Filter表
Filter表主要和進入Linux本地的數據包有關,也是默認的表。該表主要由三條鏈構成:
- INPUT:對進入主機的數據包過濾
- OUTPUT:對本地發送的數據包過濾
- FORWARD:傳遞數據包到後端計算機,與NAT有點類似。
查看本地的Filter表:
fgp@controller:~$ sudo iptables -n -t filter --list
[root@portal ~]# iptables -n -t filter --list
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
其中-n
表示不進行域名解析,-t
指定使用的表,--list
表示列出所有規則。我們發現目前沒有定義任何規則。注意鏈後面的policy爲ACCEPT
,表示若通過所有的規則都不匹配,則爲默認action accept。
接下來將通過幾個demo實例演示怎麼使用Filter表。
注意:
- 本文實驗使用的是本機虛擬機,其中宿主機地址爲192.168.56.1,虛擬機地址爲192.168.56.2,在實驗中會涉及丟棄192.168.56.1的數據包,如果您連接的是遠程雲主機,將導致和遠程主機斷開連接。
- 以下每個步驟,除非特別說明,下一個步驟執行前,務必清空上一個步驟的規則:
sudo iptables -F
首先看一個簡單的例子,把192.168.56.1加入黑名單禁止其訪問:
sudo iptables -A INPUT -i eth1 -s 192.168.56.1 -j DROP
例子中-A
表示追加規則,INPUT
是鏈名,-i
指定網卡,-s
指定源IP地址,-j
指定action,這裏爲DROP
,即丟棄包。
此時192.168.56.1這個ip不能和主機通信了,ssh會立即掉線,只能通過vnc連接了!
-s
不僅能夠指定IP地址,還可以指定網絡地址,使用-p
指定協議類型,比如我們需要丟掉所有來自192.168.56.0/24
這個網絡地址的ICMP
包,即不允許ping
:
sudo iptables -A INPUT -s 192.168.56.0/24 -i eth1 -p icmp -j DROP
輸出結果:
➜ ~ nc -z 192.168.56.2 22
Connection to 192.168.56.2 port 22 [tcp/ssh] succeeded!
➜ ~ ping 192.168.56.2
PING 192.168.56.2 (192.168.56.2): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
^C
--- 192.168.56.2 ping statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss
我們發現能夠通過nc連接主機,但ping不通。
我們還可以通過--dport
指定目標端口,比如不允許192.168.56.1這個主機ssh連接(不允許訪問22端口):
sudo iptables -A INPUT -s 192.168.56.1 -p tcp --dport 22 -i eth1 -j DROP
注意:使用--dport
或者--sport
必須同時使用-p
指定協議類型,否則無效!
以上把192.168.56.1打入了ssh黑名單,此時能夠ping通主機,但無法通過ssh連接主機。
Filter表的介紹就到此爲止,接下來看NAT表的實例。
2.NAT表
NAT表默認由以下三條鏈構成:
- PREROUTING:在進行路由判斷前所要進行的規則(DNAT/Redirect)
- POSTROUTING: 在進行路由判斷之後要進行的規則(SNAT/MASQUERADE)
- OUTPUT: 與發送的數據包有關
根據需要修改的是源IP地址還是目標IP地址,NAT可以分爲兩種:
- DNAT:需要修改目標地址(IP或者端口),使用場景爲從外網來的數據包需要映射到內部的一個私有IP,比如
46.64.22.33->192.168.56.1
。顯然作用在PREROUTING
。 - SNAT:需要修改源地址(IP或者端口),使用場景和DNAT相反,內部私有IP需要發數據包出去,必須首先映射成公有IP,比如
192.168.56.1->46.64.22.33
。顯然作用在POSTROUTING
。
首先實現介紹一個簡單的demo,端口轉發,我們把所有來自2222的tcp請求轉發到本機的22端口,顯然需要修改目標地址,因此屬於DNAT:
sudo iptables -t nat -A PREROUTING -p tcp --dport 2222 -j REDIRECT --to-ports 22
此時在192.168.56.1上使用ssh連接,指定端口爲2222:
ssh [email protected] -p 2222
我們能夠順利登錄,說明端口轉發成功。
另一個例子是使用雙網卡linux系統作爲路由器,我們有一臺服務器controller有兩個網卡:
eth0: 192.168.1.102 # 可以通外網
eth1: 192.168.56.2 # 不可以通外網,用作網關接口。
另外一臺服務器node1只有一個網卡eth1,IP地址爲192.168.56.3,不能通外網。我們設置默認路由爲controller機器的eth1:
sudo route add default gw 192.168.56.2 dev eth1
此時路由表信息爲:
fgp@node1:~$ sudo route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.56.2 0.0.0.0 UG 0 0 0 eth1
192.168.56.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
由路由表可知,node1上的數據包會發送到網關192.168.56.2,即controller節點.
接下來我們要在服務器controller上配置NAT,我們需要實現192.168.56.0/24
的IP都轉發到eth0,顯然是SNAT,修改的源地址爲eth0 IP地址192.168.1.102
:
sudo iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o eth0 -j SNAT --to-source 192.168.1.102
其中-t指定nat表,-A 指定鏈爲POSTROUTING,-s 爲源ip地址段,-o指定轉發網卡,注意-j參數指定action爲SNAT,並指定eth0 IP地址(注意eth0可能配置多個ip地址,因此必須指定--to-source
)。
此時在node1機器上檢測網絡連通性:
fgp@node1:~$ ping baidu.com -c 2
PING baidu.com (180.149.132.47) 56(84) bytes of data.
64 bytes from 180.149.132.47: icmp_seq=1 ttl=48 time=7.94 ms
64 bytes from 180.149.132.47: icmp_seq=2 ttl=48 time=6.32 ms
--- baidu.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 6.328/7.137/7.946/0.809 ms
node1能夠正常上網。
以上通過使用controller的網卡eth0作爲路由實現了node1的上網,但同時有一個問題存在,我們在指定SNAT時必須手動指定IP,如果eth0 IP地址變化了,必須修改iptables規則。顯然這樣很難維護,我們可以通過MASQUERADE
實現動態SNAT,不需要指定IP地址:
sudo iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o eth0 -j MASQUERADE
其他
使用iptables-save
能夠導出規則,使用iptables-restore
能夠從文件中導入規則。
ipset
以上我們通過iptables封IP,如果IP地址非常多,我們就需要加入很多的規則,這些規則需要一一判斷,性能會下降(線性的)。ipset能夠把多個主機放入一個集合,iptables能夠針對這個集合設置規則,既方便操作,又提高了執行效率。注意ipset並不是只能把ip放入集合,還能把網絡地址、mac地址、端口等也放入到集合中。
首先我們創建一個ipset:
sudo ipset create blacklist hash:ip
以上創建了一個blacklist集合,集合名稱後面爲存儲類型,除了hash表,還支持bitmap、link等,後面是存儲類型,我們指定的是ip,表示我們的集合元素爲ip地址。
我們爲這個blacklist集合增加一條規則,禁止訪問:
sudo iptables -I INPUT -m set --match-set blacklist src -j DROP
此時只要在blacklist的ip地址就會自動加入黑名單。
我們把192.168.56.1和192.168.56.3加入黑名單中:
sudo ipset add blacklist 192.168.56.3
sudo ipset add blacklist 192.168.56.1
此時ssh連接中斷,使用vnc連接查看:
fgp@controller:~/github/int32bit.github.io$ sudo ipset list blacklist
Name: blacklist
Type: hash:ip
Revision: 2
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 176
References: 1
Members:
192.168.56.1
192.168.56.3
把192.168.56.1移除黑名單:
sudo ipset del blacklist 192.168.56.1
我們上面的例子指定的類型爲ip,除了ip,還可以是網絡段,端口號(支持指定TCP/UDP協議),mac地址,網絡接口名稱,或者上述各種類型的組合。比如指定 hash:ip,port就是 IP地址和端口號共同作爲hash的鍵。指定類型爲net
既可以放入ip地址,也可以放入網絡地址。
另外ipset還支持timeout參數,可以指定時間,單位爲秒,超過這個時間,ipset會自動從集合中移除這個元素,比如封192.168.56.1
1分鐘時間不允許訪問
sudo ipset create blacklist hash:net timeout 300
sudo ipset add blacklist 192.168.56.1 timeout 60
以上首先創建了支持timeout的集合,這個集合默認超時時間爲300s,接着把192.168.56.1加入到集合中並設置時間爲60s。
注意:執行ipset add
時指定timeout必須保證創建的集合支持timeout參數,即設置默認的timeout時間.如果不想爲集合設置默認timeout時間,而又想支持timeout,可以設置timeout爲0,相當於默認不會超時。
總結
本文總結了Linux中的常用的網絡工具,其中包括
- 網絡配置相關:ifconfig、ip
- 路由相關:route、netstat、ip
- 查看端口工具:netstat、lsof、ss、nc、telnet
- 下載工具:curl、wget、axel
- 防火牆:iptables、ipset
- 流量相關:iftop、nethogs
- 連通性及響應速度:ping、traceroute、mtr、tracepath
- 域名相關:nslookup、dig、whois
- web服務器:python、nginx
- 抓包相關:tcpdump
- 網橋相關:ip、brctl、ifconfig、ovs