正文
网络ping不通是网络中出现频率最高的故障之一,同时也是最让人抓狂的故障,基本上大部分人都遇到过了, 如果在项目中出现网络ping不通,没有一个有序的方法去排除解决,那么很难入手,也是讨论最多的问题之一, 有不少项目经理到项目中经常遇到。我们来总结下网络ping不通是什么原因?
一、ping命令的原理
了解ping命令原因,我们来通过一个实例来了解。
假定主机A的IP地址是192.168.1.1,主机B的IP地址是192.168.1.2,都在同一子网内, 则当你在主机A上运行“Ping 192.168.1.2”后,都发生了些什么呢?
首先,Ping命令会构建一个固定格式的ICMP请求数据包, 然后由ICMP协议将这个数据包连同地址“192.168.1.2”一起交给IP层协议(和ICMP一样,实际上是一组后台运行的进程), IP层协议将以地址“192.168.1.2”作为目的地址,本机IP地址作为源地址,加上一些其他的控制信息,构建一个IP数据包, 并在一个映射表中查找出IP地址192.168.1.2所对应的物理地址(也叫MAC地址,这是数据链路层协议构建数据链路层的传输单元帧所必需的), 一并交给数据链路层。后者构建一个数据帧,目的地址是IP层传过来的物理地址,源地址则是本机的物理地址, 还要附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。
主机B收到这个数据帧后,先检查它的目的地址,并和本机的物理地址对比,如符合,则接收;否则丢弃。接收后检查该数据帧, 将IP数据包从帧中提取出来,交给本机的IP层协议。同样,IP层检查后,将有用的信息提取后交给ICMP协议, 后者处理后,马上构建一个ICMP应答包,发送给主机A,其过程和主机A发送ICMP请求包到主机B一模一样。
直接说,就是利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包, 再要求对方返回一个同样大小的数据包来确定两台网络机器是否连接相通,时延是多少。
从上面过程,就是ping命令的原理,主机A收到了主机B的一个应答包,说明两台主机之间的去、回通路均正常, 但也并不是所有网络都是正常的,下面我们来看ping不通的原因。
二、同网段ping不通的原因
ping命令不通,主要有两种情况,一种是同网段内的ip地址ping不通, 另一种是不同网段的ip地址ping不通,各个情况不一样,我们首先来看同网段ping不通的两种情况。
同网段ping不通,结果是“无法访问目标主机”
目的ip和源ip是同一网段的,ping的结果是“无法访问目标主机” ,属于ping的请求没有发出。
我们来看下,ping同网段不存的ip地址。
ping的请求发出后,返回显示“无法访问目标主机”。
什么原因呢?
说明此时,ping的需求并没有成功发出,这时,要检查:
1、对方是否开机?ip是否存在?
2、有跨交换机vlan的话,检查对应的中间trunk链路是否导通?
3、走直连路由是否正确?是否应该走默认路由,而走了直连路由。
4、子网掩码是否错误。
5、默认网关是否填写正确
同网段ping不通,结果是“超时(time out)”
目的ip和源ip是同一网段的,ping的结果是“超时或者time out” ,属于ping的请求已经成功发出了,但目标主机没有回复。
ping的请求发出后,返回显示“超时”。什么原因呢?
这种情况是ping已经成功发出了,到达了主机,但时没有得到响应,要检查:
1、检查下防火墙,防火墙禁止了对ping的回应。
2、子网掩码的设置错误,导致不在同一个网段。
3、设备硬件故障,导致设备没有对应的mac地址,无法生成路由表,而走默认路由。
4、ip冲突,或ip地址与直联路由不在同一个网段。
5、网关没有设置好
三、跨网段ping不通的原因
不同网段ping不通,可能的原因比较多,我们来看下跨网段常见的原因。
跨网段ping不通,结果是“无法访问目标主机”
跨网段出现无法访问目标主机,说明请求没有成功发出,获取不了目的ip地址与mac地址。
可能出现的原因是:
1、目的ip地址不存在。
2、检查路由表是否有缺省的路由
3、检查arp表是否有网关的mac地址
4、有网关设置错误
5、走了默认路由
跨网段ping不通,结果是“time out”
若显示time out,表示ping的request消息已经发出,目的ip的网关已经获取到目的ip的mac地址, 但是目的主机没有回复,或源主机无法收到。这些应该检查回程路由和节点回程路由。
可能的原因有:
1、检查下防火墙,是否拦截了ping的请求消息。
2、检查经过节点的路由是否正确,或者是否有回程路由。
3、回程路由的硬件网卡出口和ping的request的入口网卡不是同一个
4、交换机vlan对应的接口全部down了,导致vlan状态down,vlan的对应路由没有生成。
四、总结
当我们网络ping不通时,首先要看ping显示的结果是”无法访问目标主机“还是”超时“, 再看是同网段,还是不同网段,采取相应的分析方法,另外在分析与解决网络故障时, 我们要熟练的了解ping、arp、tracert、route这几个命令的用法,可以快速的定位ping不通的原因。 尤其是这arp、tracert、route这三个命令的用法,解决故障非常方便。
arp
arp指令用来管理系统的arp缓冲区,可以显示、删除、添加静态mac地址。ARP以各种方式操纵内核的ARP缓存。 主要选项是清除地址映射项并手动设置。为了调试目的,ARP程序还允许对ARP缓存进行完全转储。
此命令的适用范围:RedHat、RHEL、Ubuntu、CentOS、SUSE、openSUSE、Fedora。
语法:
arp [-evn] [-H type] [-i if] -a [hostname]
arp [-v] [-i if] -d hostname [pub]
arp [-v] [-H type] [-i if] -s hostname hw_ addr [temp]
arp [-v] [-H type] [-i if] -s hostname hw_ addr [netmask nm] pub
arp [-v] [-H type] [-i if] -Ds hostname ifa [netmask nm] pub
arp [-vnD] [-H type] [-i if] -f [filename]
选项列表:
选项 说明
--help 显示帮助文档
--version 显示命令版本
-H type --hw-typetype -t type 在设置或读取ARP缓存时,这个可选参数告诉ARP应该检查哪类条目。此参数的默认值为ether(即IEEE 802.3 10 Mbps以太网的硬件代码0x01)。其他可能的值有,如ARCnet(Arcnet)、PROnet(PRINET)、AX.25(Axis 25)和Net/ROM(Netrom)。
-a[hostname] | --all [hostname] 显示本机的arp缓冲区内容
-dhostname | --deletehostname 从缓冲区删除指定的地址类型
-D | -use-device 使用指定接口的mac地址
-e 使用Linux风格显示
-i if | --device if 显示指定设备的arp缓冲区
-shostnamehw_addr 设置指定主机的mac地址映射
-f filename | --file filename 类似于-s选项,只是这次地址信息是从filename设置的。数据文件的名称通常是“/etc/ether”,但这不是正式的。如果没有指定文件名“/etc/ether”作为默认值。该文件的格式很简单;它只包含带有硬件地址和由空格分隔的主机名的ASCII文本行。此外,还可以使用pub、temp和netmask标志。
-n | --numeric 使用数字方式显示
-v | --verbose 显示执行过程
在所有需要主机名的地方,人们也可以用虚线小数点表示法输入IP地址。作为兼容性的特例,主机名和硬件地址的顺序可以交换。 ARP缓存中的每个完整条目都将被标记为C标志。永久条目用M标记,已发布的条目带有P标志。
实例
1)添加静态映射
[root@localhost ~]# arp -i eth0 -s 192.168.1.6 ff:ee:ee:ee:ee:ee //将目标ip地址映射固定mac
[root@localhost ~]# arp –a //查看arp缓冲区
? (10.0.2.2) at 52:54:00:12:35:02 [ether] on eth0
? (192.168.1.6) at ff:ee:ee:ee:ee:ee [ether] PERM on eth0
2)以数字方式显示
[root@localhost ~]# arp -vn
Address HWtype HWaddress Flags Mask Iface
10.0.2.2 ether 52:54:00:12:35:02 C eth0
192.168.1.6 ether ff:ee:ee:ee:ee:ee CM eth0
Entries: 2 Skipped: 0Found: 2
tracert
linux中的使用tracert命令可以跟踪路由路径
Linux traceroute命令用于显示数据包到主机间的路径。
traceroute指令让你追踪网络数据包的路由途径,预设数据包大小是40Bytes,用户可另行设置。
语法
traceroute [-dFlnrvx][-f<存活数值>][-g<网关>...][-i<网络界面>][-m<存活数值>][-p<通信端口>][-s<来源地址>][-t<服务类型>][-w<超时秒数>][主机名称或IP地址][数据包大小]
参数说明
-d 使用Socket层级的排错功能。
-f<存活数值> 设置第一个检测数据包的存活数值TTL的大小。
-F 设置勿离断位。
-g<网关> 设置来源路由网关,最多可设置8个。
-i<网络界面> 使用指定的网络界面送出数据包。
-I 使用ICMP回应取代UDP资料信息。
-m<存活数值> 设置检测数据包的最大存活数值TTL的大小。
-n 直接使用IP地址而非主机名称。
-p<通信端口> 设置UDP传输协议的通信端口。
-r 忽略普通的Routing Table,直接将数据包送到远端主机上。
-s<来源地址> 设置本地主机送出数据包的IP地址。
-t<服务类型> 设置检测数据包的TOS数值。
-v 详细显示指令的执行过程。
-w<超时秒数> 设置等待远端主机回报的时间。
-x 开启或关闭数据包的正确性检验。
实例
[root@localhost ~]# traceroute www.baidu.com
traceroute to www.baidu.com (112.80.248.76), 30 hops max, 60 byte packets
1 gateway (10.0.2.2) 0.845 ms 0.409 ms 0.287 ms
2 * * *
3 * * *
4 * * *
5 * * *
6 * * *
7 * * *
8 * * *
9 * * *
10 * * *
11 * * *
12 * * *
13 * * *
14 * * *
15 * * *
16 * * *
17 * * *
18 * * *
19 * * *
20 * * *
21 * * *
22 * * *
23 *^C
[root@localhost ~]#
route
设置和查看路由表都可以用 route 命令
设置内核路由表的命令格式是:
route [add|del] [-net|-host] target [netmask Nm] [gw Gw] [[dev] If]
add : 添加一条路由规则
del : 删除一条路由规则
-net : 目的地址是一个网络
-host : 目的地址是一个主机
target : 目的网络或主机
netmask : 目的地址的网络掩码
gw : 路由数据包通过的网关
dev : 为路由指定的网络接口
实例
# route add -host 192.168.1.2 dev eth0
# route add -host 10.20.30.148 gw 10.20.30.40 #添加到10.20.30.148的网管
# route add -net 10.20.30.40 netmask 255.255.255.248 eth0 #添加10.20.30.40的网络
# route add -net 10.20.30.48 netmask 255.255.255.248 gw 10.20.30.41 #添加10.20.30.48的网络
# route add -net 192.168.1.0/24 eth1
# route add default gw 192.168.1.1 # 添加默认路由
# route del -host 192.168.1.2 dev eth0:0 # 删除路由
# route del -host 10.20.30.148 gw 10.20.30.40
# route del -net 10.20.30.40 netmask 255.255.255.248 eth0
# route del -net 10.20.30.48 netmask 255.255.255.248 gw 10.20.30.41
# route del -net 192.168.1.0/24 eth1
# route del default gw 192.168.1.1
netstat
用netstat检查监听端口
netstat是一个命令行工具,可以提供有关网络连接的信息。
要列出所有正在侦听的TCP或UDP端口,包括使用端口的服务和套接字状态,请使用以下命令:
sudo netstat -tunlp
此命令中使用的选项具有以下含义:
-t-显示TCP端口。
-u -显示UDP端口。
-n -显示数字地址而不是解析主机。
-l -仅显示监听端口。
-p -显示侦听器进程的PID和名称。仅当你以root用户或 sudo 用户身份运行命令时,才会显示此信息。
输出将如下所示:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0:22 0:* LISTEN 445/sshd
tcp 0 0 0:25 0:* LISTEN 929/master
tcp6 0 0 :::3306 ::* LISTEN 534/mysqld
tcp6 0 0 :::80 :::* LISTEN 515/apache2
tcp6 0 0 :::22 :::* LISTEN 445/sshd
tcp6 0 0 :::25 :::* LISTEN 929/master
tcp6 0 0 :::33060 :::* LISTEN 534/mysqld
udp 0 0 0:68 0:* 966/dhclient
在我们的案例中,重要的几列是:
Proto-套接字使用的协议。
Local Address -进程侦听的IP地址和端口号。
PID/Program name -PID和进程名称。
如果要过滤结果,请使用 grep命令。例如,要查找在TCP端口22上侦听的进程,你可以输入:
sudo netstat -tnlp | grep :22
输出显示此计算机上的端口22被SSH服务器使用:
tcp 0 0 0:22 0:* LISTEN 445/sshd
tcp6 0 0 :::22 :::* LISTEN 445/sshd
如果输出为空,则表示端口上没有监听。
你也可以根据条件过滤列表,例如PID,协议,状态等。
netstat已过时,被 ss和 ip 取代,但它仍然是检查网络连接的最常用命令。
netstat的更多详细信息可以参看 https://mp.weixin.qq.com/s/FEKnCtmrntHQ74ziMX93VA
ss
检查监听端口
ss是新的netstat。它缺少netstat的某些功能,但是公开了更多的TCP状态,并且速度稍快。命令选项基本相同,因此从netstat到ss的转换并不困难。
要使用ss获取所有监听端口的列表,请输入:
sudo ss -tunlp
输出与netstat报告的输出几乎相同:
[root@localhost ~]# ss -tunlp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:68 *:* users:(("dhclient",pid=1932,fd=6))
udp UNCONN 0 0 127.0.0.1:323 *:* users:(("chronyd",pid=702,fd=5))
udp UNCONN 0 0 [::1]:323 [::]:* users:(("chronyd",pid=702,fd=6))
tcp LISTEN 0 128 *:22 *:* users:(("sshd",pid=1126,fd=3))
tcp LISTEN 0 100 127.0.0.1:25 *:* users:(("master",pid=1394,fd=13))
tcp LISTEN 0 128 127.0.0.1:9000 *:* users:(("php-fpm",pid=1248,fd=9),("php-fpm",pid=1247,fd=9),("php-fpm",pid=1246,fd=9),("php-fpm",pid=1244,fd=9),("php-fpm",pid=1243,fd=9),("php-fpm",pid=1121,fd=7))
tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1126,fd=4))
tcp LISTEN 0 100 [::1]:25 [::]:* users:(("master",pid=1394,fd=14))
[root@localhost ~]#
lsof
检查监听端口
lsof是功能强大的命令行应用程序,可提供有关进程打开的文件的信息。
在Linux中,所有内容都是文件。你可以将套接字视为写入网络的文件。
要获取具有lsof的所有侦听TCP端口的列表,请输入:
sudo lsof -nP -iTCP -sTCP:LISTEN
使用的选项如下:
-n-不要将端口号转换为端口名称。
-p -不解析主机名,显示数字地址。
-iTCP -sTCP:LISTEN -仅显示TCP状态为LISTEN的网络文件。
[root@localhost ~]# sudo lsof -nP -iTCP -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
php-fpm 1121 root 7u IPv4 20520 0t0 TCP 127.0.0.1:9000 (LISTEN)
sshd 1126 root 3u IPv4 19701 0t0 TCP *:22 (LISTEN)
sshd 1126 root 4u IPv6 19703 0t0 TCP *:22 (LISTEN)
php-fpm 1243 apache 9u IPv4 20520 0t0 TCP 127.0.0.1:9000 (LISTEN)
php-fpm 1244 apache 9u IPv4 20520 0t0 TCP 127.0.0.1:9000 (LISTEN)
php-fpm 1246 apache 9u IPv4 20520 0t0 TCP 127.0.0.1:9000 (LISTEN)
php-fpm 1247 apache 9u IPv4 20520 0t0 TCP 127.0.0.1:9000 (LISTEN)
php-fpm 1248 apache 9u IPv4 20520 0t0 TCP 127.0.0.1:9000 (LISTEN)
master 1394 root 13u IPv4 19968 0t0 TCP 127.0.0.1:25 (LISTEN)
master 1394 root 14u IPv6 19969 0t0 TCP [::1]:25 (LISTEN)
大多数输出列名称都是不言自明的:
COMMAND,PID,USER-运行与端口关联的程序的名称,PID和用户。NAME -端口号。
要查找正在侦听特定端口(例如端口3306)的进程,可以使用:
sudo lsof -nP -iTCP:3306 -sTCP:LISTEN
输出显示MySQL服务器使用端口3306:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 534 mysql 30u IPv6 17636 0t0 TCP *:3306 (LISTEN)
telnet
telnet为用户提供了在本地计算机上完成远程主机工作的能力,因此可以通过telnet来测试端口的连通性,具体用法格式:
telnet ip port
说明:
ip:是测试主机的ip地址
port:是端口,比如80
ssh
SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议,在linux上可以通过ssh命令来测试端口的连通性,具体用法格式如下:
ssh -v -p port username@ip
说明:
-v 调试模式(会打印日志).
-p 指定端口
username:远程主机的登录用户
ip:远程主机
curl
curl是利用URL语法在命令行方式下工作的开源文件传输工具。也可以用来测试端口的连通性,具体用法:
curl ip:port
说明:
ip:是测试主机的ip地址
port:是端口,比如80
如果远程主机开通了相应的端口,都会输出信息,如果没有开通相应的端口,则没有任何提示,需要CTRL+C断开。
wget
wget是一个从网络上自动下载文件的自由工具,支持通过HTTP、HTTPS、FTP三个最常见的TCP/IP协议下载,并可以使用HTTP代理。 wget名称的由来是“World Wide Web”与“get”的结合,它也可以用来测试端口的连通性具体用法:
wget ip:port
说明:
ip:是测试主机的ip地址
port:是端口,比如80
如果远程主机不存在端口则会一直提示连接主机。
参考资料
网络ping不通是什么原因?看过就明白 https://mp.weixin.qq.com/s/q1gk4aPddxTDbbJOv-Z88g
Linux基础命令 arp https://www.cnblogs.com/wj78080458/p/10358033.html
Linux traceroute命令 https://www.runoob.com/linux/linux-comm-traceroute.html
linux 路由表设置 之 route 指令详解 https://www.cnblogs.com/baiduboy/p/7278715.html
netstat 还能这么玩儿? https://mp.weixin.qq.com/s/FEKnCtmrntHQ74ziMX93VA
Linux中是谁占用了我的端口 https://mp.weixin.qq.com/s/ayvbOKnEdX5OsUyPlbHUIg
Linux测试端口是否ping的方法 https://blog.csdn.net/hqbootstrap1/article/details/88833878