ssh登錄太慢了,每次都要20s

背景

大家工作時,少不了ssh登錄各個服務器,我這邊手裏也有很多服務器,有一些登錄很快就進去了,有些要卡半天才能進去。之前以爲是公司網絡問題,每次也就忍了,這次突然不想忍了,決定定位一下。

我這邊的服務器是10.80.121.46。因爲這個問題是可復現的,算是個好問題,於是在本地開了wireshark,ssh登錄,看看能不能看出端倪。

host 10.80.121.46 and tcp port  22

image-20240403150300958

可以看到,服務端在00:13,發了第一個消息過來;過了20s,發了第二個消息過來。

總的來說,應該是服務端問題。

定位過程

看日誌

由於是ssh這種加密了的協議,抓包也看不出個啥。所以我首先的思路是看看sshd這個服務端進程的日誌。sshd是systemd管理的,所以看看狀態先。

image-20240403150748358

這種的話,一般也能看到最新的日誌,如果要看完整的日誌,可以用如下命令:

journalctl -u sshd
ps: journalctl -u sshd -f  可以像tailf那樣持續跟蹤日誌

但是,發現只有info級別的日誌,也看不出什麼特別.

Apr 03 15:27:30 nginx2 sshd[87616]: Accepted password for root from 10.0.235.72 port 11481 ssh2

接下來,又看了下其他日誌:

/var/log/messages:

Apr  3 15:27:30 year-account-nginx2 systemd-logind: New session 13336 of user root.
Apr  3 15:27:30 year-account-nginx2 systemd: Started Session 13336 of user root.

/var/log/secure:

Apr  3 15:27:30 year-account-nginx2 sshd[87616]: Accepted password for root from 10.0.235.72 port 11481 ssh2
Apr  3 15:27:30 year-account-nginx2 sshd[87616]: pam_unix(sshd:session): session opened for user root by (uid=0)

反正看了好些日誌,沒啥用,這邊上個鏈接,講linux下的各種日誌。

https://www.plesk.com/blog/featured/linux-logs-explained/

https://www.eurovps.com/blog/important-linux-log-files-you-must-be-monitoring/

開啓debug日誌

上網查了下,怎麼開啓sshd的debug級別日誌,結論如下:

vim /etc/ssh/sshd_config
加一行:
LogLevel DEBUG

這個LogLevel的取值有哪些呢,具體可以在機器上執行:

man sshd_config

沒想到取值還有更逆天的:

image-20240403154906764

我之前就是在debug級別下測試的,然後看日誌:

journalctl -u sshd -f

image-20240403155216416

看到出現了20s的間隔,但是,還是沒有什麼錯誤或者警告。當時,我就開始上網查了,但是這次,咱們要不試試把日誌級別弄成DEBUG3:

image-20240403155612165

這裏日誌細了一些,但還是看不太出來啥問題。這個10.0.235.72,是我本機windows的ip。

服務端dns抓包

經過上網衝浪,發現很多文章提到了一點,就是sshd會拿着我們客戶端的ip,去dns 服務器查詢ip對應的主機名(域名)。很明顯,我這個ip,肯定是沒什麼域名的。大概率是這個原因,但是基於嚴謹的角度考慮,我還是先找找證據。

dns服務器對外的端口是53,所以我抓的就是這個端口的網絡包:

image-20240403160126500

可以發現,本機是給兩個dns服務器發請求的,分別是8.8.8.8 8.8.4.4

看下機器的dns服務器配置:

vim /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4

不知道爲啥是這個地址,反正是運維同事給的。

測試了端口通不通,發現tcp不通,udp不知道咋測(試了下netcat、nmap,沒太弄懂)

ping也不通,不知道是真不通,還是對端禁ping了。

這些都不重要,重要的是,這個報文也不知道是啥意思,看起來和我的問題沒什麼關係。

strace排查

暫時放下dns這塊,準備strace試試,反正,死馬當活馬醫。

strace這個一般用得少,選項記不住,一開始就這麼試試:

netstat -nltp|grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      93585/sshd          
tcp        0      0 0.0.0.0:4822            0.0.0.0:*               LISTEN      31633/nginx: master 
tcp6       0      0 :::22                   :::*                    LISTEN      93585/sshd    

拿到sshd pid爲93585,開啓strace:

image-20240403162504572

但是啥也沒看出來。

找了下以前筆記,加了幾個選項:

strace -p 121920 -s 1000  -t -e trace=network,file,desc,process

-s: 字符串顯示1000個字符串,不截斷(默認是32,會看不全)
-t:顯示時間
-e trace=network,file,desc,process,監控網絡、文件、文件描述符、進程相關的系統調用

image-20240403162625728

這次信息多一點,還是啥都看不出來。

上網查

沒法了,把之前dns抓的包拿下來用wireshark分析分析。

image-20240403162958052

image-20240403163038782

這個dns查詢,有點看不懂,直接拿關鍵字搜了下,大家看如下鏈接吧:

https://www.cloudflare.com/zh-cn/learning/dns/dns-records/dns-ptr-record/

image-20240403163719503

難怪,dns進行反向查找時,客戶端ip是反的,我的實際ip是:10.0.235.72

到了上圖,就變成了:

image-20240403163844082

也難怪我沒看出來,這個基本算是一個強力證據了,大概率是dns解析的問題,畢竟用了我的ip。

修改sshd配置

那就禁用這個機制吧,方式如下:

vim /etc/ssh/sshd_config
UseDNS no

然後重啓sshd
systemctl restart sshd

這樣基本就ok了。重新試了下,再沒有卡20s了,秒登錄。

繼續探索strace

找到問題原因後,strace我又繼續研究了下。原來是少了個選項,-f:

       -f
       --follow-forks
                   Trace  child  processes  as  they  are  created  by  currently traced processes as a result of the fork(2), vfork(2) and
                   clone(2) system calls.  Note that -p PID -f will attach all threads of process PID if it  is  multi-threaded,  not  only
                   thread with thread_id = PID.

這個選項是跟蹤子進程的系統調用,因爲,sshd收到一個客戶端連接時,會fork一個新進程出來。前面都忘了加-f,所以導致沒跟蹤到。

換下命令:

strace -p 93585 -s 1000  -t -e trace=network,file,desc,process -f

image-20240403170112853

這次可以跟蹤了。

補充

在寫這篇文章的時候,對一個地方產生了疑問。一般看日誌的時候,對於systemd管理的service,我會看journalctl,也會看/var/log/messages,經常的情況是,在journalctl中的日誌,在/var/log/messages中也能看到。

查了下兩者的機制,參考:

https://serverfault.com/questions/1150014/can-a-service-managed-by-systemd-send-its-logs-somewhere-other-than-var-log-mes

systemd會寫日誌到一些文件(journalctl就會讀這些文件),然後,另一個後臺進程rsyslogd,也會讀這些日誌,然後寫到/var/log/messages這些文件中。

[root@year-account-nginx2 log]# ps -ef|grep rsys
root       1614      1  0  2022 ?        00:46:28 /usr/sbin/rsyslogd -n

image-20240403171017316

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