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 

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