一款好用到爆的工具socat!網友們直呼 666

netcat 有一個最重要的變種 socat (socket cat),值得花一篇完整的文章介紹一下,它不僅語義統一,功能靈活,除了完成 nc 能完成的所有任務外,還有很多實用的用法:

基本命令就是

socat [參數]  <地址1>  <地址2>

使用 socat 需要提供兩個地址,然後 socat 做的事情就是把這兩個地址的數據流串起來,把第左邊地址的輸出數據傳給右邊,同時又把右邊輸出的數據傳到左邊。

最簡單的地址就是一個減號 “-”,代表標準輸入輸出,而在命令行輸入:

socat - -     # 把標準輸入和標準輸出對接,輸入什麼顯示什麼

就會對接標準輸入和標準輸出,你鍵盤敲什麼屏幕上就顯示什麼,類似無參數的 cat 命令。除了減號地址外,socat 還支持:TCP, TCP-LISTEN, UDP, UDP-LISTEN, OPEN, EXEC, SOCKS, PROXY 等多種地址,用於端口監聽、鏈接,文件和進程讀寫,代理橋接等等。

因此使用 socat 其實就是學習各類地址的定義及搭配方法,我們繼續以實用例子開始。

網絡測試

這個類似 nc 的連通性測試,兩臺主機到底網絡能否聯通:

socat - TCP-LISTEN:8080        # 終端1 上啓動 server 監聽 TCP
socat - TCP:localhost:8080     # 終端2 上啓動 client 鏈接 TCP

在終端 1 上輸入第一行命令作爲服務端,並在終端 2 上輸入第二行命令作爲客戶端去鏈接。

聯通後在終端 2 上隨便輸入點什麼,就能顯示在終端 1 上,反之亦然,因爲兩條命令都是把標準輸入輸出和網絡串起來,因此把兩個地址交換一下也是等價的:

socat TCP-LISTEN:8080 -               # 終端1 上啓動 server 監聽 TCP
socat TCP:localhost:8080 -            # 終端2 上啓動 client 鏈接 TCP

因爲 socat 就是把左右兩個地址的輸入輸出接在一起,因此顛倒左右兩個地址影響不大,除非前面指明 -u 或者 -U 顯示指明數據 “從左到右” 還是“從右到左”。

同 netcat 一樣,如果客戶端結束的話,服務端也會結束,但是 socat 還可以加額外參數:

socat - TCP-LISTEN:8080,fork,reuseaddr      # 終端1 上啓動 server
socat - TCP:localhost:8080                  # 終端2 上啓動 client

服務端在 TCP-LISTEN 地址後面加了 fork 的參數後,就能同時應答多個鏈接過來的客戶端,每個客戶端會 fork 一個進程出來進行通信,加上 reuseaddr 可以防止鏈接沒斷開玩無法監聽的問題。

剛纔也說了使用 socat 主要就是學習描述各種地址,那麼想測試 UDP 的話修改一下就行:

socat - UDP-LISTEN:8080               # 終端1 上啓動 server 監聽 UDP
socat - UDP:localhost:8080            # 終端2 上啓動 client 鏈接 UDP

即可進行測試。

端口轉發

在主機上監聽一個 8080 端口,將 8080 端口所有流量轉發給遠程機器的 80 端口:

socat TCP-LISTEN:8080,fork,reuseaddr  TCP:192.168.1.3:80

那麼連到這臺機器上 8080 端口的所有鏈接,相當於鏈接了 192.168.1.3 這臺機器的 80 端口,命令中交換左右兩個地址一樣是等價的。

這裏 socat 比 nc 強的地方就體現出來了,nc 做轉發時只能轉發 1 次,第一條鏈接 accept 並且關閉以後 nc 就退出了,無法接受新鏈接,因此 nc 只適合單次使用。而 socat 加上 fork 以後,每次 accept 一個鏈接都會 fork 出一份來不影響接收其他的新連接,這樣 socat 就可以當一個端口轉發服務,一直啓動在那裏。還可以用 supervisor 託管起來,開機自動啓動。

還可以用這個功能暴露一些 127.0.0.1 的端口出來供外面訪問,比起 nc 的臨時救急使用一下的場景,socat 是可以當一個服務長期運行的。

遠程登錄

地址除了 TCP 和 TCP-LISTEN 外,另外一個重要的地址類型就是 EXEC 可以執行程序並且把輸入輸出和另外一個地址串起來,比如服務端:

socat TCP-LISTEN:8080,fork,reuseaddr  EXEC:/usr/bin/bash    # 服務端提供 shell
socat - TCP:localhost:8080                                  # 客戶端登錄

完善一點可以加些參數:

socat TCP-LISTEN:8080,fork,reuseaddr  EXEC:/usr/bin/bash,pty,stderr   # 服務端
socat file:`tty`,raw,echo=0 TCP:localhost:8080                        # 客戶端

這樣可以把 bash 的標準錯誤重定向給標準輸出,並且用終端模式運行。客戶端可以像剛纔那樣登錄,但是還可以更高級點,用 tty 的方式訪問,這樣基本就得到了一個全功能的交互式終端了,可以在裏面運行 vim, emacs 之類的程序。

更高級一點,使用 root 運行:

socat TCP-LISTEN:23,reuseaddr,fork,crlf exec:/bin/login,pty,setsid,setpgid,stderr,ctty

相當於在 23 端口啓動了一個 telnetd 的服務,可以用 telnet 客戶端來鏈接。

網頁服務

首先編寫一個腳本:web.sh

#! /bin/bash
echo -e -n "HTTP/1.0 200\r\n"
echo -e -n "Content-Type:text/html\r\n"
echo -e -n "\r\n"

echo "<html><body>"
echo "now is $(date)"
echo "</body></html>"

這裏我們用 SYSTEM 地址類型代替原來的 EXEC 執行命令,因爲可以後面寫 shell 命令:

socat TCP-LISTEN:8080,fork,reuseaddr SYSTEM:"bash web.sh"

這時你就可以用瀏覽器訪問:http://localhost:8080 的端口了:

相當於每次請求的時候,socat 都會 fork 一個進程出來然後執行後面的命令,啓動上面的腳本程序,並且將腳本的標準輸入輸出重定向給網絡鏈接。

相當於原始的 cgi 程序了,我們可以用 shell 直接完成一個 cgi 程序並由 socat 提供 cgi 服務,偶然需要暴露一些服務器信息的話,可以這樣弄一下,返回的 html 裏搞一個自動刷新,然後打開瀏覽器,實時監控服務器的情況。

文件傳輸

臨時需要傳輸下文件,無需 scp:

socat -u TCP-LISTEN:8080 open:record.log,create    # 服務端接收文件
socat -u open:record.log TCP:localhost:8080        # 客戶端發送文件

這裏用了 -u 參數,意思是數據從左邊的地址單向傳輸到右邊的地址,大寫 -U 的話是從右邊單向傳輸到左邊。

透明代理

第一句是用於 socks 代理的,第二句用於 HTTP 代理:

socat TCP-LISTEN:<本地端口>,reuseaddr,fork SOCKS:<代理服務器IP>:<遠程地址>:<遠程端口>,socksport=<代理服務器端口>
socat TCP-LISTEN:<本地端口>,reuseaddr,fork PROXY:<代理服務器IP>:<遠程地址>:<遠程端口>,proxyport=<代理服務器端口>

他們都可以把本地端口的請求轉換成使用代理服務器訪問的請求,比如:

socat TCP-LISTEN:1234,fork SOCKS4A:127.0.0.1:google.com:80,socksport=5678

那麼鏈接本地的 1234 端口,相當於通過代理服務器 127.0.0.1:5678 去鏈接 google.com 的 80 端口了,這裏用了 SOCKS4A ,後面 A 的意思是讓代理服務器去解析域名。

其他用途

還有很多高級用法,比如用 socat 一鍵開啓 vpn 網絡,使用 socat 將 ssl 流量轉化爲裸的 tcp 流量等等,可以參考官方文檔。不難發現,上面幾個用法都比原始的 nc 要強很多,但是 nc 更小巧一些,也更容易獲得:不管是路由器上,還是 busybox 的內置命令中,還是 nmap 工具包,都有 nc 的存在。

所以很多時候條件限制可能你只有 netcat 可以使用,那麼就用 netcat,其他時候看你哪個用的更熟練一些就用哪個。不管端口轉發還是傳文件,還是透明代理,每項其實都有專業的軟件可以用,但 netcat/socat 用熟了以後,他們的靈活度非常大,能夠搭配組合出千變萬化的功能來,在你只是偶爾需要處理某件事情,又不想或者無法安裝專用軟件的情況下,完全可以使用這兩個工具完成很多任務。

所以,socat/netcat 還有 tcpdump 一起,可以說是最值得掌握的三條網絡命令。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/uzb7CDOClfpzU5dv7uhJ_Q