端口转发之 socat (二)

360次阅读
没有评论

共计 4341 个字符,预计需要花费 11 分钟才能阅读完成。

背景

之前写过一篇 端口转发之 nginx (一),用于解决公司内网环境下的 tcp 端口转发问题。

实际使用后,发现存在一些不太令人满意的地方:

  1. 不会保留日志
  2. 性能偏弱
  3. 四层转发的配置不够灵活

同时,我近期购买了一台国内大带宽服务器A,同时我还有一台海外服务器B。为了解决直连B网络不佳的问题,我会用A来进行中转,即实现
用户 –> A ip:port​ –> B ip:port​,需要能够同时转发 tcp 和 udp 包。

基于此,我了解到了 socat ,可以很好的解决当前问题。

socat 是什么

Socat(SOcket CAT)是一个功能强大的网络工具,用于在两个不同的数据流之间建立连接。它可以创建虚拟串口、连接网络套接字、进行数据转发和调试等操作。Socat是在UNIX和类UNIX系统上使用的开源软件,可以在命令行中使用。

Socat的主要功能包括:

  1. 建立连接:Socat可以在不同的网络套接字之间建立连接。它支持TCP、UDP、IPv4、IPv6等协议,并且可以在不同的主机之间进行连接。并且几乎没有连接数的限制。
  2. 数据转发:Socat可以将数据从一个数据流转发到另一个数据流。它可以在本地主机上进行转发,也可以在远程主机之间进行转发。这使得它在网络调试和数据重定向方面非常有用。
  3. 虚拟串口:Socat可以创建虚拟串口,使得应用程序可以通过串口与其他设备进行通信。这对于模拟串口设备或与硬件设备进行交互非常有用。
  4. 加密和认证:Socat支持使用SSL和TLS加密协议进行连接,并且可以进行客户端和服务器的身份验证。这使得它在安全通信方面非常有用。
  5. 端口扫描:Socat可以用于扫描主机上的端口,以确定哪些端口处于打开状态。这对于网络安全测试和漏洞评估非常有用。

Socat的命令行语法非常灵活,可以根据具体的需求进行配置。它提供了丰富的选项和参数,可以用于控制连接的行为和属性。Socat还支持脚本编程,可以编写复杂的连接脚本和数据处理逻辑。

实操

socat 的安装和配置转发极其便捷。

安装 socat

操作系统: Ubuntu 20.04

# 安装
apt-get install socat -y

# 查看版本
# socat -V
socat by Gerhard Rieger and contributors - see www.dest-unreach.org
socat version 1.7.3.3 on Oct 26 2019 17:42:04
...

配置转发

需要更复杂的转发场景,可以执行 socat -h​ 查看支持的选项和参数,下面介绍如何在IPV4场景下进行 tcp & udp 端口转发,例如将本机的 9999 端口 转发至远端IP的9999端口。

TCP 转发示例

socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:远端IP:9999

UDP 转发示例

socat -T 600 UDP4-LISTEN:9999,reuseaddr,fork UDP4:远端IP:9999

参数说明

  • TCP4-LISTEN:本地被转发的tcp4端口
  • UDP4-LISTEN:本地被转发的udp4端口
  • reuseaddr:允许本地端口地址重用
  • fork:将 Socat 进程转变为守护进程,并在接收到连接时创建子进程处理连接
  • TCP4:远端IP 和 tcp端口
  • UDP4:远端IP 和 udp端口

使用 supervisor 管理 socat

执行上述命令后,进程将会被前台执行以实现端口转发。实际使用时,我们肯定期望后台运行它。

后台运行有很多种方式,例如使用nohup,或者screen。在网上查阅文章时,大部分文章都介绍这两种方式,但是我并不建议,最简单的理由就是这两种方式不够稳定。如果进程中断后,将无法再次自动拉起。

有思考过使用 systemd 来进行管理,最后发现它也不是合适的方式。为什么?

socat 原生不支持多端口或端口段转发,每条转发规则仅允许单对单执行,那么我刚才的两条规则,就需要写两个 systemd 单元,会极大增加维护的成本,得不偿失。

最终,我选择使用 supervisor 对 socat 进行管理。

# 安装 supervisor
apt install supervisor

# 编辑 supervisor 配置文件,请将 远端IP 替换为实际的IP
# vim /etc/supervisor/conf.d/socat.conf
[program:socat_tcp]
command=socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:远端IP:9999
autostart=true
autorestart=true
stderr_logfile=/var/log/socat_tcp.err.log
stdout_logfile=/var/log/socat_tcp.out.log

[program:socat_udp]
command=socat -T 600 UDP4-LISTEN:9999,reuseaddr,fork UDP4:远端IP:9999
autostart=true
autorestart=true
stderr_logfile=/var/log/socat_udp.err.log
stdout_logfile=/var/log/socat_udp.out.log


# 启动 supervisor
systemctl start supervisor


# 查看 supervisor 状态
# systemctl status supervisor
# supervisorctl 
socat_tcp                        RUNNING   pid 247013, uptime 0:01:38
socat_udp                        RUNNING   pid 247014, uptime 0:01:38

在使用包管理器安装 supervisor 后,默认会配置开启自启,无需额外配置。可以看看它的配置文件

  • autostart=true
  • autorestart=true
# cat  /etc/supervisor/supervisord.conf 
; supervisor config file

[unix_http_server]
file=/var/run/supervisor.sock   ; (the path to the socket file)
chmod=0700                       ; sockef file mode (default 0700)

[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor            ; ('AUTO' child log dir, default $TEMP)
autostart=true
autorestart=true
...

我们可以再看看 socat 启动的进程:

# ps -ef|grep socat
root      228688       1  0 14:23 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      245720       1  0 17:33 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      246206       1  0 17:45 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      246852       1  0 18:02 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      246901       1  0 18:04 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      246920       1  0 18:05 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      246984       1  0 18:07 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247013  247011  0 18:08 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247014  247011  0 18:08 ?        00:00:00 socat -T 600 UDP4-LISTEN:9999,reuseaddr,fork UDP4:1.1.1.1:9999
root      247140  247013  0 18:09 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247175  247013  0 18:10 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247235  247013  0 18:12 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247242  247013  0 18:12 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247260  247013  0 18:13 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247261  247013  0 18:13 ?        00:00:00 socat TCP4-LISTEN:9999,reuseaddr,fork TCP4:1.1.1.1:9999
root      247277  246427  0 18:14 pts/0    00:00:00 grep --color=auto socat

至此,所有配置完毕。

结论

socat 在实际使用中,配置简单且灵活,对于四层转发场景是一个很好的解决手段。

但是它仍有一个不太方便的点:

由于socat运行在用户态,无法实现批量的端口转发,例如它不能做到批量转发本地的10000~20000端口到 远端。只能每条命令启动一个socat进程,每个socat进程实现单个端口转发。

如果有这种需求,可以使用运行在内核态的 iptables 来实现,下篇文章再来进行介绍。

引用链接

正文完
 
pengyinwei
版权声明:本站原创文章,由 pengyinwei 2023-09-22发表,共计4341字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处:https://www.opshub.cn
评论(没有评论)