• Linux 网络工具中的瑞士军刀


    独立博客阅读:https://ryan4yin.space/posts/socat-netcat/

    个人笔记,不保证正确!

    文中的命令均在 macOS Big Sur 和 Opensuse Tumbleweed 上测试通过

    socat & netcat

    netcat(network cat) 是一个历史悠久的网络工具包,被称作 TCP/IP 的瑞士军刀,各大 Linux 发行版都有默认安装 openbsd 版本的 netcat,它的命令行名称为 nc.

    而 socat(socket cat),官方文档描述它是 "netcat++" (extended design, new implementation),项目比较活跃,kubernetes-client(kubectl) 底层就是使用的它做各种流量转发。

    在不方便安装 socat 的环境中,我们可以使用系统自带的 netcat.
    而在其他环境,可以考虑优先使用 socat.

    一、简介

    socat 的基本命令格式:

    socat [参数] 地址1 地址2
    

    给 socat 提供两个地址,socat 干的活就是把两个地址的流对接起来。左边地址的输出传给右边,同时又把右边地址的输出传给左边,也就是一个双向的数据管道

    听起来好像没啥特别的,但是实际上计算机网络干的活也就是数据传输而已,却影响了整个世界,不可小觑它的功能。

    socat 支持非常多的地址类型:-/stdio,TCP, TCP-LISTEN, UDP, UDP-LISTEN, OPEN, EXEC, SOCKS, PROXY 等等,可用于端口监听、链接,文件和进程读写,代理桥接等等。

    socat 的功能就是这么简单,命令行参数也很简洁,唯一需要花点精力学习的就是它各种地址的定义和搭配写法。

    而 netcat 定义貌似没这么严谨,可以简单的理解为网络版的 cat 命令 2333

    二、安装方法

    各发行版都自带 netcat,包名通常为 nc-openbsd,因此这里只介绍 socat 的安装方法:

    # Debian/Ubuntu
    sudo apt install socat
    
    # CentOS/RedHat
    sudo yum install socat
    
    # macOS
    brew install socat
    

    其他发行版基本也都可以使用包管理器安装 socat

    三、常用命令

    1. 网络调试

    1.1 检测远程端口的可连接性(确认防火墙没问题)

    以前你可能学过如何用 telnet 来做这项测试,不过现在很多发行版基本都不自带 telnet 了,还需要额外安装。
    telnet 差不多已经快寿终正寝了,还是建议使用更专业的 socat/netcat

    使用 socat/netcat 检测远程端口的可连接性:

    # -d[ddd] 增加日志详细程度,-dd  Prints fatal, error, warning, and notice messages.
    socat -dd - TCP:192.168.1.252:3306
    
    # -v 显示详细信息
    # -z 不发送数据,效果为立即关闭连接,快速得出结果
    nc -vz 192.168.1.2 8080
    
    # -vv 显示更详细的内容
    # -w2 超时时间设为 2 秒
    # 使用 nc 做简单的端口扫描
    nc -vv -w2 -z 192.168.1.2 20-500
    

    1.2 测试本机端口是否能正常被外部访问(检测防火墙、路由)

    在本机监听一个 TCP 端口,接收到的内容传到 stdout,同时将 stdin 的输入传给客户端:

    # 服务端启动命令,socat/nc 二选一
    socat TCP-LISTEN:7000 -
    # -l --listening
    nc -l 7000
    
    # 客户端连接命令,socat/nc 二选一
    socat TCP:192.168.31.123:7000 -
    nc 192.168.11.123 7000
    

    UDP 协议的测试也非常类似,使用 netcat 的示例如下:

    # 服务端,只监听 ipv4
    nc -u -l 8080
    
    # 客户端
    nc -u 192.168.31.123 8080
    # 客户端本机测试,注意 localhost 会被优先解析为 ipv6! 这会导致服务端(ipv4)的 nc 接收不到数据!
    nc -u localhost 8080
    

    使用 socat 的 UDP 测试示例如下:

    socat UDP-LISTEN:7000 -
    
    socat UDP:192.168.31.123:7000 -
    

    1.3 调试 TLS 协议

    参考 socat 官方文档:Securing Traffic Between two Socat Instances Using SSL

    测试证书及私钥的生成参见 [TLS 协议、TLS 证书、TLS 证书的配置方法、TLS 加密的破解手段]({{< ref "about-tls-cert/index.md" >}})

    模拟一个 mTLS 服务器,监听 4433 端口,接收到的数据同样输出到 stdout:

    # socat 需要使用同时包含证书和私钥的 pem 文件,生成方法如下
    cat server.key server.crt > server.pem
    cat client.key client.crt > client.pem
    
    # 服务端启动命令
    socat openssl-listen:4433,reuseaddr,cert=server.pem,cafile=client.crt -
    
    # 客户端连接命令
    socat - openssl-connect:192.168.31.123:4433,cert=client.pem,cafile=server.crt
    # 或者使用 curl 连接(我们知道 ca.crt 和 server.crt 都能被用做 cacert/cafile)
    curl -v --cacert ca.crt --cert client.crt --key client.key --tls-max 1.2 https://192.168.31.123:4433
    

    上面的命令使用了 mTLS 双向认证的协议,可通过设定 verify=0 来关掉客户端认证,示例如下:

    
    # socat 需要使用同时包含证书和私钥的 pem 文件,生成方法如下
    cat server.key server.crt > server.pem
    
    # 服务端启动命令
    socat openssl-listen:4433,reuseaddr,cert=server.pem,verify=0 -
    
    # 客户端连接命令,如果 ip/域名不受证书保护,就也需要添加 verify=0
    socat - openssl-connect:192.168.31.123:4433,cafile=server.crt
    # 或者使用 curl 连接,证书无效请添加 -k 跳过证书验证
    curl -v --cacert server.crt https://192.168.31.123:4433
    

    2. 数据传输

    通常传输文件时,我都习惯使用 scp/ssh/rsync,但是 socat 其实也可以传输文件。

    以将 demo.tar.gz 从主机 A 发送到主机 B 为例,
    首先在数据发送方 A 执行如下命令:

    # -u 表示数据只从左边的地址单向传输给右边(socat 默认是一个双向管道)
    # -U 和 -u 相反,数据只从右边单向传输给左边
    socat -u open:demo.tar.gz tcp-listen:2000,reuseaddr
    

    然后在数据接收方 B 执行如下命令,就能把文件接收到:

    socat -u tcp:192.168.1.252:2000 open:demo.tar.gz,create
    # 如果觉得太繁琐,也可以直接通过 stdout 重定向
    socat -u tcp:192.168.1.252:2000 - > demo.tar.gz
    

    使用 netcat 也可以实现数据传输:

    # 先在接收方启动服务端
    nc -l -p 8080 > demo.tar.gz
    # 再在发送方启动客户端发送数据
    nc 192.168.1.2 8080 < demo.tar.gz
    

    3. 担当临时的 web 服务器

    使用 fork reuseaddr SYSTEM 三个命令,再用 systemd/supervisor 管理一下,就可以用几行命令实现一个简单的后台服务器。

    下面的命令将监听 8080 端口,并将数据流和 web.py 的 stdio 连接起来,可以直接使用浏览器访问 http://<ip>:8080 来查看效果。

    socat TCP-LISTEN:8080,reuseaddr,fork SYSTEM:"python3 web.py"
    

    假设 web.py 的内容为:

    print("hello world")
    

    curl localhost:8080 就应该会输出 hello world

    4. 端口转发

    监听 8080 端口,建立该端口与 baidu.com:80 之间的双向管道:

    socat TCP-LISTEN:8080,fork,reuseaddr  TCP:baidu.com:80
    

    拿 curl 命令测试一下,应该能正常访问到百度:

    # 注意指定 Host
    curl -v -H 'Host: baidu.com' localhost:8080
    

    参考

  • 相关阅读:
    【Sparse】关于__attribute__((bitwise)),__le32,__be32等的理解【转】
    设备树中ranges属性分析(1)【转】
    Linux内核API sprint_symbol【转】
    Linux内核--网络协议栈深入分析(二)--sk_buff的操作函数【转】
    浅析SkipList跳跃表原理及代码实现【转】
    关于kernel module签名【转】
    apt-get 更新指定软件_Linux系统 aptget 命令的使用:安装、更新、卸载软件包【转】
    如何挂载ubi文件系统【转】
    伙伴系统之伙伴系统概述--Linux内存管理(十五)【转】
    精确时间协议PTP研究【转】
  • 原文地址:https://www.cnblogs.com/kirito-c/p/14666619.html
Copyright © 2020-2023  润新知