的路由分層定位)
FTP 這個(gè)東西說起來老但真到要用的場合一點(diǎn)不含糊——老系統(tǒng)的對(duì)賬文件、設(shè)備日志回傳、第三方接口的批量數(shù)據(jù)交換很多還壓在它身上。而一旦連不上報(bào)出來的那兩句話往往只有兩種形態(tài)ftp connect: 拒絕連接和ftp connect: 沒有到主機(jī)的路由。前者是 TCP 層被人當(dāng)面關(guān)上了門后者是網(wǎng)絡(luò)層壓根沒找到門在哪。這兩種報(bào)錯(cuò)看起來都像“連不上”但排查路徑幾乎是兩條不同的路混著查只會(huì)把自己繞進(jìn)去。這篇內(nèi)容面向的是正在被 FTP 連接問題卡住的人不管是剛接手運(yùn)維的新手還是寫了幾年腳本、被客戶一句“你們 FTP 連不上”懟回來的開發(fā)。下面我會(huì)把這兩類報(bào)錯(cuò)的底層成因拆開講清楚再給出一套可以照著敲命令的分層排查流程最后附上被動(dòng)模式、防火墻、云上安全組這些實(shí)際最容易翻車的環(huán)節(jié)。文中涉及的系統(tǒng)和配置均按通用發(fā)行版描述具體路徑以你自己環(huán)境為準(zhǔn)。1. 先搞清楚兩種報(bào)錯(cuò)到底差在哪很多人排查 FTP 的第一步是打開客戶端反復(fù)重連看運(yùn)氣。這個(gè)動(dòng)作除了消耗耐心沒有別的產(chǎn)出。真正該做的第一件事是把這兩句報(bào)錯(cuò)翻譯成網(wǎng)絡(luò)分層里的具體位置。它們對(duì)應(yīng)的不是同一個(gè)層也不是同一類故障。1.1 拒絕連接TCP 層收到的那個(gè) RST 包拒絕連接Connection refused在協(xié)議層面的含義非常明確客戶端發(fā)出了 SYN對(duì)端回了一個(gè) RST。這說明什么說明數(shù)據(jù)包已經(jīng)成功到達(dá)了目標(biāo)主機(jī)路由是通的目標(biāo)主機(jī)的內(nèi)核也正常處理了這個(gè)包只是內(nèi)核告訴客戶端“這個(gè)端口上沒有任何進(jìn)程在等你的連接”于是回了拒絕。這條鏈路里路由器、交換機(jī)、中間網(wǎng)絡(luò)設(shè)備全都是好的問題百分之百出在目標(biāo)主機(jī)這一側(cè)的應(yīng)用層或者主機(jī)防火墻層。你可以把它理解成地址找對(duì)了樓也進(jìn)去了前臺(tái)告訴你“這個(gè)房間沒人”。具體到 FTP21 端口被拒絕最常見的幾個(gè)原因按出現(xiàn)頻率排大概是FTP 服務(wù)進(jìn)程根本沒起來或者起來之后崩了服務(wù)起來了但只監(jiān)聽了127.0.0.1外部從公網(wǎng)或內(nèi)網(wǎng)其它機(jī)器連進(jìn)來就等不到主機(jī)防火墻用了REJECT --reject-with tcp-reset這類策略主動(dòng)回 RST端口寫錯(cuò)了客戶端連 21服務(wù)端改成了 2121或者中間做了端口映射但映射規(guī)則沒生效端口被別的進(jìn)程占了FTP 啟動(dòng)失敗表面上像是沒開。注意最后一條特別有迷惑性。systemctl status顯示 active但實(shí)際綁定失敗了這種情況在配置改過端口、或者機(jī)器上跑了兩套同類服務(wù)時(shí)很常見。1.2 沒有到主機(jī)的路由網(wǎng)絡(luò)層就已經(jīng)斷了沒有到主機(jī)的路由No route to host是另一回事。它通常意味著客戶端的協(xié)議棧在發(fā)包階段就沒有找到可達(dá)路徑或者是中途收到了 ICMP 的不可達(dá)消息。跟“拒絕連接”比起來它更靠下、更靠前。典型場景有這么幾類。第一類是客戶端本機(jī)的路由表里沒有到目標(biāo)網(wǎng)段的條目也沒有默認(rèn)網(wǎng)關(guān)包發(fā)不出去。第二類是目標(biāo)主機(jī)不在同一個(gè)二層網(wǎng)絡(luò)中間網(wǎng)關(guān)不認(rèn)識(shí)這個(gè)網(wǎng)段。第三類是防火墻策略把包丟了并且回了一個(gè) ICMP host prohibited客戶端就會(huì)把它解釋成“沒有到主機(jī)的路由”。第四類是 ARP 解析失敗同網(wǎng)段內(nèi)目標(biāo)主機(jī)沒響應(yīng) ARP 請(qǐng)求內(nèi)核報(bào) host unreachable。這里有個(gè)很關(guān)鍵的認(rèn)知點(diǎn)沒有到主機(jī)的路由不一定真的是路由問題。如果防火墻用REJECT --reject-with icmp-host-prohibited客戶端收到的就是 ICMP 類型 3 代碼 10表現(xiàn)和真的路由不通幾乎一模一樣。我在實(shí)際排查里遇到過好幾次最后發(fā)現(xiàn)是目標(biāo)機(jī)上的防火墻規(guī)則順序?qū)懛戳税言试S規(guī)則放在了拒絕規(guī)則后面。而如果是DROP策略客戶端那邊通常表現(xiàn)為連接一直掛著最后超時(shí)而不是立刻報(bào)錯(cuò)。所以“立刻報(bào)錯(cuò)”和“轉(zhuǎn)圈到超時(shí)”是區(qū)分 REJECT 和 DROP 的一個(gè)很實(shí)用的手感。1.3 一張表分清兩類故障的邊界對(duì)比項(xiàng)拒絕連接沒有到主機(jī)的路由報(bào)錯(cuò)層級(jí)傳輸層TCP網(wǎng)絡(luò)層IP/ICMP報(bào)文特征收到 RST收到 ICMP 不可達(dá)或本機(jī)路由失敗目標(biāo)主機(jī)是否可達(dá)可達(dá)內(nèi)核正常響應(yīng)可能不可達(dá)也可能被策略偽裝成不可達(dá)服務(wù)是否在監(jiān)聽沒監(jiān)聽或監(jiān)聽地址不對(duì)與服務(wù)監(jiān)聽狀態(tài)基本無關(guān)常見原因服務(wù)未啟動(dòng)、綁 127.0.0.1、防火墻 REJECT路由缺失、網(wǎng)關(guān)錯(cuò)誤、防火墻 ICMP REJECT、網(wǎng)段隔離排查起點(diǎn)目標(biāo)機(jī)ss -lntp客戶端ip route與ping把這張表記在心里后面所有動(dòng)作都是往下鉆。拿反了方向就會(huì)出現(xiàn)“明明防火墻全放開了還是連不上”這種僵局因?yàn)閱栴}根本不在防火墻的策略內(nèi)容上而在包有沒有到。2. 排查前的準(zhǔn)備把“分層”這件事落到命令行上分層排查不是一句口號(hào)它得變成一條固定順序的命令清單。順序?qū)α艘淮尉湍馨逊秶车粢话腠樞騺y了改了一堆配置問題還在原地。2.1 排查順序?yàn)槭裁幢仨毷亲韵露霞偃?FTP 連不上我先看服務(wù)狀態(tài)還是先 ping答案必須是先 ping。理由很直白如果網(wǎng)絡(luò)層都不通你去看/etc/vsftpd/vsftpd.conf里的每一個(gè)參數(shù)都是白費(fèi)。反過來如果 ping 得通、端口探測被拒那再去查服務(wù)配置才有意義。我固定的排查順序是四步一步不跳鏈路與地址確認(rèn)本機(jī)網(wǎng)卡有沒有地址、掩碼對(duì)不對(duì)、網(wǎng)關(guān)通不通網(wǎng)絡(luò)可達(dá)ping目標(biāo) IP看是超時(shí)、不可達(dá)還是通端口可達(dá)telnet或nc探 21 端口看是拒絕還是超時(shí)應(yīng)用狀態(tài)服務(wù)進(jìn)程、監(jiān)聽地址、配置文件、日志。這四步跑完故障基本已經(jīng)被鎖死在某一層了。下面每一步我會(huì)展開說但順序千萬別換來換去。2.2 手上要備好的幾把工具工欲善其事工具先裝齊。基礎(chǔ)鏡像里常常缺telnet和nc很多人到現(xiàn)場才發(fā)現(xiàn)敲不出來。ping基礎(chǔ)連通性幾乎所有系統(tǒng)自帶ip route/route -n看路由表和默認(rèn)網(wǎng)關(guān)telnet或nc -vz探測端口判斷拒絕還是超時(shí)traceroute或mtr看路徑在哪一跳斷掉ss -lntp看本機(jī)監(jiān)聽端口和對(duì)應(yīng)進(jìn)程tcpdump抓包看 SYN 有沒有發(fā)出去、有沒有回包這是終極大招firewall-cmd --list-all/iptables -L -n -v看防火墻實(shí)際生效規(guī)則。提示在某些精簡系統(tǒng)上telnet客戶端和nc默認(rèn)都沒裝。提前準(zhǔn)備好比到了現(xiàn)場臨時(shí)找包要省太多時(shí)間。2.3 記錄基線信息別一上來就改配置我踩過最虧的一次坑是接手一臺(tái)別人配過的機(jī)器一上來就懷疑防火墻結(jié)果把本來正確的規(guī)則改壞了最后發(fā)現(xiàn)只是 FTP 配置里listenNO。從那以后我給自己定了個(gè)規(guī)矩動(dòng)手之前先把現(xiàn)場信息原樣記錄一份。至少要記下這些目標(biāo)機(jī)的ip addr、ip route、ss -lntp | grep 21、防火墻規(guī)則全量輸出、FTP 服務(wù)狀態(tài)與最近 50 行日志。客戶端這邊記下ip route和ping結(jié)果。這些信息除了幫你定位還有一個(gè)作用——出問題時(shí)能快速回滾不至于越修越亂。2.4 用 tcpdump 看清 SYN 的去向這一步很多人覺得高級(jí)其實(shí)它是最樸素的判斷手段。在服務(wù)端執(zhí)行抓包同時(shí)在客戶端發(fā)起連接# 服務(wù)端抓 21 端口的包 tcpdump -i any -nn port 21 -c 20如果抓到了客戶端來的 SYN但服務(wù)端沒回 SYN-ACK那就是本機(jī)沒監(jiān)聽或者防火墻攔了如果回了 RST那就是端口沒人等對(duì)應(yīng)“拒絕連接”如果壓根沒抓到 SYN問題在中間網(wǎng)絡(luò)或者路由對(duì)應(yīng)“沒有到主機(jī)的路由”這一類。一次抓包能省掉半小時(shí)的猜測。3. 拒絕連接Connection refused的逐層拆解與修復(fù)確定是“拒絕連接”之后排查范圍就縮小到目標(biāo)機(jī)內(nèi)部了。下面這四步我基本按順序來絕大多數(shù)情況在第二步就能定位。3.1 第一步確認(rèn)服務(wù)到底起沒起先在目標(biāo)機(jī)上執(zhí)行systemctl status vsftpd看兩個(gè)東西Active那一行是active (running)還是failed以及下面日志里有沒有Failed to start之類的內(nèi)容。如果狀態(tài)是 failed直接看日志journalctl -u vsftpd -n 80 --no-pager日志里常見的是配置文件語法錯(cuò)誤、端口被占用、權(quán)限不足。比如500 OOPS: could not bind listening IPv4 socket基本就是端口被占了或者配置沖突。如果狀態(tài)是 running也別高興太早。繼續(xù)看監(jiān)聽ss -lntp | grep -E :(21|ftp)正常應(yīng)該看到類似LISTEN 0 32 0.0.0.0:21 0.0.0.0:* users:((vsftpd,pid1234,fd3))的輸出。如果這里是127.0.0.1:21那就是下一個(gè)問題了。3.2 第二步確認(rèn)監(jiān)聽地址綁對(duì)沒綁對(duì)ss輸出里那個(gè)0.0.0.0:21和127.0.0.1:21的區(qū)別決定了外部能不能連進(jìn)來。0.0.0.0表示監(jiān)聽所有 IPv4 地址127.0.0.1表示只聽本機(jī)回環(huán)。造成只聽回環(huán)的原因在 vsftpd 上通常是這兩行配置listenYES listen_address127.0.0.1listen_address一旦被指定成回環(huán)地址外部連接必然被拒。改法是把這一行注釋掉或者明確寫成機(jī)器的業(yè)務(wù) IPlistenYES listen_ipv6NO # listen_address127.0.0.1改完記得systemctl restart vsftpd然后再用ss確認(rèn)一次。這里有個(gè)細(xì)節(jié)listenYES和listen_ipv6YES不能同時(shí)打開否則 vsftpd 啟動(dòng)會(huì)直接報(bào)錯(cuò)退出而systemctl status有時(shí)候顯示得很含糊容易誤判成服務(wù)正常。3.3 第三步防火墻是 REJECT 還是 DROP監(jiān)聽沒問題端口也對(duì)外了那就要看防火墻。先確認(rèn)防火墻狀態(tài)# firewalld 環(huán)境 firewall-cmd --state firewall-cmd --list-all # iptables 環(huán)境 iptables -L INPUT -n -v --line-numbers判斷的關(guān)鍵在于規(guī)則里用的是REJECT還是DROP。REJECT會(huì)往客戶端回一個(gè)消息DROP是直接丟棄、不回任何東西。所以客戶端立刻報(bào)“拒絕連接”多半是REJECT --reject-with tcp-reset客戶端一直轉(zhuǎn)圈到超時(shí)多半是DROP客戶端報(bào)“沒有到主機(jī)的路由”可能是REJECT --reject-with icmp-host-prohibited。放行 21 端口的寫法firewalld 環(huán)境下firewall-cmd --permanent --add-serviceftp firewall-cmd --reload或者按端口放行firewall-cmd --permanent --add-port21/tcp firewall-cmd --reloadiptables 環(huán)境下iptables -I INPUT -p tcp --dport 21 -j ACCEPT注意-I是插到鏈?zhǔn)?A是追加到鏈尾。如果原有規(guī)則里有前置的拒絕規(guī)則-A加在后面的允許規(guī)則根本不會(huì)被匹配到。這就是我在第 1 節(jié)提到的“規(guī)則順序?qū)懛础钡牡湫秃蠊?。注意?iptables 規(guī)則前先確認(rèn)有沒有持久化機(jī)制否則重啟后規(guī)則全丟第二天又是同一個(gè)故障。iptables-save配合netfilter-persistent或iptables-services是常見做法。3.4 第四步云主機(jī)上的安全組與端口映射如果目標(biāo)機(jī)跑在云上主機(jī)內(nèi)部防火墻全放開了還是拒絕連接那就要往上找一層。云平臺(tái)通常有獨(dú)立于操作系統(tǒng)的網(wǎng)絡(luò)訪問控制一般叫安全組或者網(wǎng)絡(luò) ACL它在實(shí)例外面生效你在機(jī)器里iptables -L是看不到的。排查方式是登錄云控制臺(tái)找到該實(shí)例綁定的安全組看入方向規(guī)則里有沒有放行 21 端口源地址范圍是否覆蓋了你的客戶端 IP。這里最常見的兩個(gè)坑一是安全組只放行了內(nèi)網(wǎng)地址而你從公網(wǎng)連二是規(guī)則的優(yōu)先級(jí)被更靠前的拒絕規(guī)則蓋掉了。還有一種情況是中間做了端口映射比如公網(wǎng) 2121 映射到內(nèi)網(wǎng) 21。這時(shí)候客戶端必須連 2121連 21 自然是被拒。同時(shí)被動(dòng)模式還要額外處理數(shù)據(jù)端口這個(gè)在第 5 節(jié)展開。3.5 驗(yàn)證與回歸測試改完不要只在自己機(jī)器上試一次就收工。我的驗(yàn)證清單是這樣的本機(jī)telnet 127.0.0.1 21確認(rèn)服務(wù)活著同網(wǎng)段另一臺(tái)機(jī)器telnet 內(nèi)網(wǎng)IP 21確認(rèn)內(nèi)網(wǎng)可達(dá)客戶端所在網(wǎng)絡(luò)telnet 公網(wǎng)IP 21確認(rèn)外部可達(dá)用真實(shí) FTP 客戶端登錄一次做一次ls和一次put重啟一次服務(wù)再重復(fù)第 4 步確認(rèn)配置持久化沒問題。第 5 步很多人省掉結(jié)果下次機(jī)器重啟故障復(fù)現(xiàn)。配置這東西不重啟驗(yàn)證一遍就等于沒改。4. 沒有到主機(jī)的路由No route to host的逐層拆解與修復(fù)這類報(bào)錯(cuò)的排查思路和上一節(jié)完全不同。核心是回答一個(gè)問題包到底有沒有離開客戶端以及離開之后走到了哪一跳。4.1 先 ping 一下但 ping 不通不代表服務(wù)有問題第一步永遠(yuǎn)是ping 目標(biāo)IP。但要注意ping不通有三種可能含義完全不同Destination Host Unreachable本機(jī)或中間設(shè)備明確告訴你到不了路由或 ARP 有問題Request timeout包發(fā)出去了沒有任何回應(yīng)可能是對(duì)方禁 ping也可能是防火墻 DROPName or service not known這是域名解析問題壓根還沒到網(wǎng)絡(luò)層。關(guān)鍵認(rèn)知是服務(wù)器禁 ping 是很常見的加固手段ping 不通不代表 FTP 連不上。所以 ping 只能作為參考不能作為結(jié)論。真正有決定性的還是端口探測nc -vz -w 3 目標(biāo)IP 21或者telnet 目標(biāo)IP 21看返回是Connection refused、Connection timed out還是No route to host。這三者的含義和排查方向完全不同前面表格里已經(jīng)對(duì)上了。4.2 路由表與網(wǎng)關(guān)檢查確認(rèn)是本機(jī)路由問題時(shí)先看路由表ip route輸出里要關(guān)注兩件事有沒有到目標(biāo)網(wǎng)段的具體路由以及default via后面那個(gè)網(wǎng)關(guān)地址是不是當(dāng)前網(wǎng)段的合法地址。如果默認(rèn)網(wǎng)關(guān)寫錯(cuò)了比如網(wǎng)段是192.168.10.0/24網(wǎng)關(guān)卻寫成了192.168.20.1那所有跨網(wǎng)段的包都發(fā)不出去。再看本機(jī)地址和掩碼ip addr掩碼寫錯(cuò)是很容易被忽略的坑。把/24寫成/16本機(jī)會(huì)認(rèn)為整個(gè)192.168.0.0/16都在同一個(gè)二層網(wǎng)絡(luò)里于是對(duì)本來需要經(jīng)過網(wǎng)關(guān)的地址直接發(fā) ARP 請(qǐng)求結(jié)果自然是 host unreachable。這種錯(cuò)誤在手工配 IP 的機(jī)器上出現(xiàn)頻率相當(dāng)高。4.3 防火墻 DROP 策略的典型表現(xiàn)前面說過DROP通常表現(xiàn)為超時(shí)而不是“沒有到主機(jī)的路由”但如果規(guī)則用的是REJECT --reject-with icmp-host-prohibited客戶端收到的就是 ICMP 類型 3 代碼 10報(bào)錯(cuò)文案和真正的路由不通一模一樣。判斷方法是看目標(biāo)機(jī)上的規(guī)則iptables -L INPUT -n -v --line-numbers如果看到類似這樣的規(guī)則REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited并且它排在允許 21 端口的規(guī)則前面那故障原因就找到了。處理方式是調(diào)整順序把允許規(guī)則插到它前面iptables -I INPUT 1 -p tcp --dport 21 -j ACCEPT-I INPUT 1里的1表示插到第一條。這個(gè)數(shù)字很關(guān)鍵插錯(cuò)位置等于沒插。4.4 網(wǎng)段隔離、VLAN 與云上子網(wǎng)如果客戶端和服務(wù)端不在同一個(gè)二層網(wǎng)絡(luò)中間又有多層網(wǎng)絡(luò)設(shè)備那就要考慮策略隔離了。企業(yè)內(nèi)網(wǎng)常見的做法是把辦公網(wǎng)、服務(wù)器網(wǎng)、測試網(wǎng)分到不同 VLANVLAN 之間的訪問由三層設(shè)備上的 ACL 控制。ACL 默認(rèn)拒絕的時(shí)候表現(xiàn)出來就是“沒有到主機(jī)的路由”。云上的情況類似但對(duì)象換成了子網(wǎng)和路由表。兩個(gè)子網(wǎng)之間如果沒有對(duì)等連接或者路由條目包就出不去。這時(shí)候在實(shí)例內(nèi)部怎么改防火墻都沒用得去網(wǎng)絡(luò)配置層面加路由。排查手段是traceroutetraceroute -n -T -p 21 目標(biāo)IP-T表示用 TCP 探測-p 21指定端口??摧敵鲈谀囊惶_始出現(xiàn)* * *就能大致判斷阻斷點(diǎn)在哪一層設(shè)備上。如果第一跳就是星號(hào)問題在本機(jī)或網(wǎng)關(guān)如果中間幾跳正常、最后斷了問題在靠近目標(biāo)的一側(cè)。4.5 復(fù)現(xiàn)驗(yàn)證方法改完路由或者 ACL 之后驗(yàn)證要覆蓋兩個(gè)方向。正向驗(yàn)證是從客戶端 ping 和探端口反向驗(yàn)證是從服務(wù)端 ping 客戶端同時(shí)看服務(wù)端有沒有收到 SYN# 服務(wù)端抓包確認(rèn)有 SYN 進(jìn)來 tcpdump -i any -nn tcp port 21 and tcp[tcpflags] tcp-syn ! 0抓到 SYN 說明網(wǎng)絡(luò)通了剩下的就是應(yīng)用層的事抓不到說明包還在路上被攔著。這個(gè)判定比反復(fù)改配置靠譜得多。5. 連上了卻傳不了文件被動(dòng)模式那些坑端口通了、登錄成功了、ls也出來了結(jié)果put一個(gè)文件卡死不動(dòng)——這是 FTP 最經(jīng)典的“第二步故障”。它跟前面兩類報(bào)錯(cuò)不是一回事但對(duì)使用者的感受是一樣的連不上。5.1 主動(dòng)模式與被動(dòng)模式的本質(zhì)區(qū)別FTP 用兩條連接一條控制連接走 21 端口一條數(shù)據(jù)連接傳文件??刂七B接永遠(yuǎn)是客戶端主動(dòng)連服務(wù)端這個(gè)沒問題。數(shù)據(jù)連接的方向取決于模式。主動(dòng)模式PORT下服務(wù)端從自己的 20 端口主動(dòng)連客戶端的一個(gè)隨機(jī)端口。問題在于客戶端通常在 NAT 或者防火墻后面服務(wù)端根本連不進(jìn)去于是卡住。被動(dòng)模式PASV下客戶端向服務(wù)端要一個(gè)端口服務(wù)端返回一個(gè)隨機(jī)高位端口客戶端主動(dòng)去連這個(gè)端口。這個(gè)方向?qū)蛻舳擞押盟袁F(xiàn)代客戶端默認(rèn)都用被動(dòng)模式。但被動(dòng)模式又帶來一個(gè)新問題服務(wù)端返回的那個(gè)端口是隨機(jī)的防火墻如果只放行了 21數(shù)據(jù)連接必然被攔。表現(xiàn)出來就是登錄正常、列目錄正常一傳文件就超時(shí)。5.2 pasv_min_port 與 pasv_max_port 的配置解決辦法是把被動(dòng)模式的端口范圍固定下來然后在防火墻上放行這一段。vsftpd 的配置是這樣pasv_enableYES pasv_min_port30000 pasv_max_port30100范圍選多大按并發(fā)連接數(shù)估。每個(gè)數(shù)據(jù)傳輸占一個(gè)端口理論最大并發(fā)數(shù)等于端口數(shù)量。一般內(nèi)部使用 100 個(gè)端口足夠50 個(gè)并發(fā)以內(nèi)完全扛得住。如果用戶量大可以放到 500 個(gè)。如果服務(wù)端在 NAT 后面還要加一行pasv_address告訴客戶端應(yīng)該連哪個(gè)公網(wǎng)地址pasv_address公網(wǎng)IP這一行不加服務(wù)端會(huì)把內(nèi)網(wǎng)地址返回給客戶端客戶端拿著一個(gè)內(nèi)網(wǎng) IP 去連自然連不上。這是我見過最多的被動(dòng)模式故障原因沒有之一。5.3 防火墻放行數(shù)據(jù)端口配置改完防火墻同步放行firewall-cmd --permanent --add-port30000-30100/tcp firewall-cmd --reload云平臺(tái)的安全組也要同步加一條規(guī)則端口范圍寫30000-30100協(xié)議 TCP。這一步經(jīng)常被漏掉因?yàn)樵跈C(jī)器內(nèi)部折騰半天都正常一出公網(wǎng)就廢。還有 SELinux 這一層。如果系統(tǒng)開了 SELinux 且策略比較嚴(yán)FTP 讀寫家目錄會(huì)被攔getenforce setsebool -P ftpd_full_access on-P表示持久化不加的話重啟就失效。改完用getsebool ftpd_full_access確認(rèn)一下狀態(tài)是 on。6. 常見問題速查表與避坑經(jīng)驗(yàn)前面幾節(jié)講的是原理和流程這一節(jié)講的是我這些年實(shí)際踩出來的經(jīng)驗(yàn)。有些坑在文檔里不會(huì)寫但遇到了能讓人折騰一整天。6.1 排查速查表現(xiàn)象最可能的原因快速驗(yàn)證處理動(dòng)作立刻報(bào)拒絕連接服務(wù)未啟動(dòng) / 綁回環(huán)ss -lntp | grep 21啟動(dòng)服務(wù)改listen_address立刻報(bào)拒絕連接服務(wù)正常防火墻 REJECTiptables -L -n -v放行 21注意規(guī)則順序轉(zhuǎn)圈后超時(shí)防火墻 DROPtcpdump看有無回包檢查 DROP 規(guī)則與安全組報(bào)沒有到主機(jī)的路由路由缺失或 ICMP REJECTip route、traceroute補(bǔ)路由或調(diào)整 REJECT 類型ping 通但端口不通服務(wù)未監(jiān)聽或端口錯(cuò)誤nc -vz探端口核對(duì)端口與監(jiān)聽地址登錄成功但ls卡住被動(dòng)模式端口被攔客戶端開 PASV 調(diào)試日志固定 pasv 端口段并放行登錄成功但put失敗目錄權(quán)限或 SELinuxls -ld、getenforce改權(quán)限或開ftpd_full_access重啟后故障復(fù)現(xiàn)配置未持久化重啟再測一遍iptables-save、--permanent6.2 幾個(gè)我踩過的坑坑一systemctl status是 active但端口沒起來。有一次配置文件里listen和listen_ipv6同時(shí)為 YESvsftpd 啟動(dòng)后立刻退出但 systemd 的重啟策略讓它反復(fù)拉起status看到的永遠(yuǎn)是 active。真正定位是靠journalctl里的重復(fù)報(bào)錯(cuò)。所以看狀態(tài)一定要配合看日志和看監(jiān)聽??佣耐?iptables 忘了持久化。這個(gè)坑的殺傷力在于它有延遲——當(dāng)天一切正常第二天機(jī)器重啟故障原樣復(fù)現(xiàn)而且看起來像是“莫名其妙又壞了”。現(xiàn)在我的習(xí)慣是改完立刻iptables-save /etc/sysconfig/iptablesfirewalld 環(huán)境則確保每條命令都帶--permanent??尤蛻舳朔阑饓σ矓r。一直在服務(wù)端折騰最后發(fā)現(xiàn)是客戶端本機(jī)的出站規(guī)則攔了高位端口。被動(dòng)模式下客戶端要連服務(wù)端的 30000 以上端口有些終端安全軟件默認(rèn)只放行常用端口。這個(gè)排查起來很快在客戶端抓個(gè)包就一目了然??铀腘AT 環(huán)境下的pasv_address忘了配。表現(xiàn)是內(nèi)網(wǎng)用戶全正常外網(wǎng)用戶一律傳不了文件。因?yàn)榉?wù)端返回的是內(nèi)網(wǎng)地址外網(wǎng)客戶端拿著192.168.x.x去連當(dāng)然連不上。這個(gè)問題的隱蔽性在于日志里看不出任何異常只能靠抓包或者看客戶端返回的 PASV 響應(yīng)內(nèi)容??游遒~號(hào)密碼對(duì)了但登錄被拒。這不是網(wǎng)絡(luò)問題是認(rèn)證層。常見原因是ftpusers和user_list文件里默認(rèn)拒絕了一批系統(tǒng)賬戶或者chroot_local_userYES配合家目錄可寫導(dǎo)致 vsftpd 拒絕登錄。日志在/var/log/secure里搜vsftpd關(guān)鍵字能直接看到原因。6.3 長期運(yùn)維上的一點(diǎn)建議FTP 這套東西本身沒有健康檢查機(jī)制出問題往往是被動(dòng)發(fā)現(xiàn)的。我的做法是在監(jiān)控里加兩個(gè)探測點(diǎn)一個(gè)是 21 端口的 TCP 連通性探測另一個(gè)是真實(shí)的登錄加列目錄操作頻率五分鐘一次。前者能發(fā)現(xiàn)服務(wù)掛了后者能發(fā)現(xiàn)被動(dòng)模式配置被改壞了。另外配置變更一定要留記錄。FTP 的配置文件不長但每一項(xiàng)都影響面很大尤其是被動(dòng)模式那幾行。我見過一次事故是有人為了“優(yōu)化性能”把pasv_min_port和pasv_max_port注釋掉了結(jié)果防火墻規(guī)則對(duì)應(yīng)的端口段全部失效外網(wǎng)用戶全部傳不了文件而內(nèi)網(wǎng)測試一切正常直到客戶投訴才發(fā)現(xiàn)。最后再分享一個(gè)小技巧排查 FTP 問題時(shí)盡量用命令行客戶端ftp或lftp而不是圖形客戶端。命令行會(huì)原樣輸出服務(wù)端的響應(yīng)碼比如227 Entering Passive Mode (192,168,1,10,117,40)這里面的數(shù)字就是服務(wù)端返回的被動(dòng)端口117*2564030000一眼就能看出它返回的是不是內(nèi)網(wǎng)地址、端口在不在放行范圍內(nèi)。圖形客戶端把這些信息全藏起來了排查時(shí)等于蒙著眼睛。我在實(shí)際處理這類問題的體會(huì)是FTP 報(bào)錯(cuò)文案的區(qū)分度其實(shí)很高拒絕連接和沒有到主機(jī)的路由已經(jīng)把排查方向指得很明確難的不是判斷而是忍住不跳過驗(yàn)證步驟直接改配置。按鏈路、網(wǎng)絡(luò)、端口、應(yīng)用這四層老老實(shí)實(shí)走一遍絕大多數(shù)問題在十分鐘內(nèi)就能定位到具體那一行配置上。