Linux 排查端口时通时不通的问题

一、问题描述

用户有两个vpc,其中一个vpc访问vpc外的机器正常,另外一个vpc内的主机访问云外物理机22端口就时通时不通的。

 二、排查过程

2.1 为验证规律写个脚本分别在两个不同的vpc中找了一台主机远程监控目标服务的22端口,如果不通则发送告警到企业微信机器人

使用ping命令测试,一直是通的,即使端口不通,ping也是通的。

#!/usr/bin/env python
# -*- coding:utf-8-*-
# Time      : 2022/4/20 13:55
# Author    : lzlx
# Contact   : [email protected]
# File      : 端口监控.py
# Software  : PyCharm

import socket
import time
import requests

ip = "10.3.13.22"
port = "80"

url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=自己机器人的key"
headers = {"Content-Type": "application/json",
           "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"}
while True:
    time.sleep(3)
    data = {
        "msgtype": "text",
        "text": {
            "content": "{} - {}:{}端口不通".format((time.strftime("%Y-%m-%d %H:%M:%S")), ip, port)
        }
    }
    sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.settimeout(1)
    try:
        sk.connect(('{}'.format(ip), int('{}'.format(port))))
    except Exception:
        requests.post(url=url, json=data)
    sk.close()

2.2 监控后发现经常性的时断时通,没有什么规律,怀疑是不是路由的链路有什么变化导致的

使用以下两个命令在正常和断开的情况下都测试过,路由链路是一致的,没有变化,机器上也没有做vpn隧道之类的。

# traceroute 10.3.13.22
# mtr 10.3.13.22

2.3 继续验证,从VPC的主机到目标机器测试,依旧是时断时续的,使用tracepath 测试链路可以到目标主机,端口依旧不通,问题应该出在目标主机

# tracepath -n -p 22 10.3.13.22
.......
12:  10.3.13.22                                           14.140ms reached
     Resume: pmtu 1500 hops 12 back 12 

# 以上证明转发是正常的,可以到达目标主机的22端口

# 使用命令测试依旧超时
# telnet 10.3.13.22 22
Trying 10.3.13.22...
telnet: Unable to connect to remote host: Connection time out

# nc -uz 10.3.13.22 22
nc: connect to 10.3.13.22 port 22 (tcp) failed: Connection time out 

2.4 登录目标主机抓包,经查看/var/log/secure中访问的IP是对端vpc的IP地址

# tcpdump -i eth0 host 10.5.5.1 and port 22 -w a.cap

抓包分析发现收到包之后三次握手不成功,只有客户端发送过来的SYN包,并没有服务端返回的SYN+ACK包,所以无法建立连接。

正常的三次握手应该是这样的

 

 2.5 继续排查系统内有效端口范围、TIMEWAT情况和网络队列溢出

 

 

 发现有很多SYN包被dropped掉了

2.6 经过查看内核参数发现这两个内核参数都打开了

 三、故障原因,及处理方法

因为2.6内核以上中tcp_timestamps默认是打开的,所以当打开 tcp_tw_recycle时会导致部分通过NAT上网client无法正确连接服务器,故障表现为client发出SYN后无法收到server返回 的SYN+ACK,推荐的解决方法是关闭tcp_tw_recycle,打开tcp_tw_reuse解决TIME-WAIT过多的问题。

echo 0 > /proc/sys/net/ipv4/tcp_tw_recycle
tcp_tw_recycle 设置为 1 会开启系统对 TIME_WAIT 状态的 socket 的快速回收。开启这个功能,系统就会存下 TCP 连接的时间戳,当同一个 IP 地址过来的包的时间戳小于缓存的时间戳,系统就直接丢包,“回收”这个 socket。这个选项同样需要开启 tcp_timestamp 才生效。
开启这个功能是有很大风险的,服务器端会根据同一个 IP 发送过来的包的时间戳来判断是否丢包,而时间戳是根据发包的客户端的系统时间得来的,如果服务端收到的包是同一出口 IP 而系统时间不一样的两个客户端的包,就有可能会丢包,可能出现的情况就是一个局域网内有的客户端能连接服务端,有的不能。具体原因是客户端处于NAT模式下,出口ip可能是同一个ip,不同客户端的发送的时间戳可能乱序,服务器会检查相同ip地址发送来过的包的时间戳是不是小于缓存的时间戳,如果不是,直接丢掉。
 
参考链接:
https://mp.weixin.qq.com/s/yH3PzGEFopbpA-jw4MythQ

https://blog.csdn.net/weixin_39809584/article/details/111107816 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章