linux网络工具

ping

这个命令不用多说,我们通常使用这个命令判断网络的连通性以及网速,偶尔还顺带当做域名解析使用(查看域名的 IP):

ping google.com

默认使用该命令会一直发送 ICMP 包直到用户手动中止,可以使用-c命令指定发送数据包的个数,使用-W指定最长等待时间,如果有多张网卡,还可以通过-I指定发送包的网卡。

fgp@controller:~$ ping -c 2 -I eth0 -W 2 baidu.com
ping: Warning: source address might be selected on device other than eth0.
PING baidu.com (111.13.101.208) from 192.168.56.2 eth0: 56(84) bytes of data.
From controller (192.168.56.2) icmp_seq=1 Destination Host Unreachable
From controller (192.168.56.2) icmp_seq=2 Destination Host Unreachable

--- baidu.com ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1008ms
pipe 2

以上命令会由 eth0 网卡发送两个包,并且最长等待 2 秒时间,执行完后会自动退出。

小技巧: 在 ping 过程中按下ctrl+|会打印出当前的 summary 信息,统计当前发送包数量、接收数量、丢包率等。

其他比如-b发送广播,另外注意 ping 只能使用 ipv4,如果需要使用 ipv6,可以使用ping6命令。

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

以上Genmask0.0.0.0的表示默认路由,即连接外网的路由。

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!

从结果中发现,该主机打开了2280端口。

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

可见成功连接到localhost22端口,说明端口已经打开,还输出了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 命令可以说是无比强大了,它完全可以替换ifconfignetstatroutearp等命令,比如查看网卡 eth1 IP 地址:

fgp@controller:~$ sudo ip addr ls  dev eth1
3: eth1:  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:  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 leaforest.github.io
traceroute to leaforest.github.io (185.199.109.153), 30 hops max, 60 byte packets
 1  124.16.87.254  2.057 ms  2.244 ms  2.261 ms
 2  10.10.10.41  0.990 ms  1.026 ms  1.021 ms
 3  210.77.16.126  2.471 ms  2.445 ms  2.451 ms
 4  10.3.3.1  3.113 ms  3.085 ms  3.092 ms
 5  10.1.1.1  2.746 ms  2.718 ms  2.725 ms
 ...

可以看到,从主机到leaforest.github.io共经过 30 跳,并统计了每一跳间的响应时间。

另外可以参考tracepath

mtr

mtr 是常用的网络诊断工具(a network diagnostic tool),它把 ping 和 traceroute 并入一个程序的网络诊断工具中并实时刷新。

ss

ss 命令也是一个查看网络连接的工具(another utility to investigate sockets),用来显示处于活动状态的套接字信息。

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

python

没看错,就是 python,它是一种面向对象、解释型程序设计语言,由 Guido van Rossum 于 1989 年发明,第一个公开发行版发行于 1991 年。放在这里,主要是使用 python 非常方便的开启 web 服务器共享文件(为了共享文件,不是每个人都乐意部署一个 ftp 服务器或者通过 scp 发送):

此时可以使用python 2SimpleHTTPServer模块快速启动一个服务器共享文件,不过注意这个服务器是单进程单线程,因此同时只支持一个连接,如果需要考虑高并发,只能使用 ftp 或者 nginx 了。

cd shares/
python -m SimpleHTTPServer

或者python 3

python3 -m http.server

此时会在本地监听 8000 端口,对方使用浏览器访问你的 ip 和端口即可下载共享的文件,非常方便。

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 请求,发送数据为用户名以及密码(模拟表单输入)。

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 还支持指定下载文件的格式,比如只下载 jpg 图片

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

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/leaforest.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.11 分钟时间不允许访问

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

这些工具非常强大,本文只介绍了最基本的使用方法,更详细的使用可以参考命令文档。

你可能感兴趣的:(linux网络工具)