使用socat进行端口转发

socat | 半卷

socat是一个多功能的网络工具,名字来由是” SOcket CAT”,因此可以看出它基于socket,能够折腾socket相关的无数事情。

当然这些都不是我关心的重点。我发现并尝试使用socat的原因可以参看此前的一次端口转发的尝试,本文的重点是介绍一下我对socat的使用心得,以及折腾了一个小时的GENTOO版socat服务脚本。

为了表示对网络先驱的尊重,首先贴参考文章:

Port Forwarding in user space [INFO]》和《How to forward port in user space using socat

socat其实可以看作是netcat的加强N倍版,因此乍一看socat的命令行,那叫一个复杂。不过仔细一看后,其实发现socat的参数也是很有规律、简洁的。例如,我需要的转发功能是:

对于所有15000端口的TCP访问,一律转发到 server.wesnoth.org:15000 上。

于是,对应的命令就是:

1
socat -d -d -lf /var/log/socat.log TCP4-LISTEN:15000,reuseaddr,fork,su=nobody TCP4:server.wesnoth.org:15000

“-d -d -lf /var/log/socat.log”是参数,前面两个连续的-d -d代表调试信息的输出级别,-lf则指定输出信息的保存文件。

“TCP4-LISTEN:15000,reuseaddr,fork,su=nobody”是一号地址,代表在15000端口上进行TCP4协议的监听,复用绑定的IP,每次又连接到来就fork复制一个进程进行处理,同时将执行用户设置为nobody用户。

“TCP4:server.wesnoth.org:15000″是二号地址,代表将socat监听到的任何请求,转发到server.wesnoth.org:15000上去。

但是在服务器上运行的命令,最好还是写成为一个服务脚本,这样便于后续重启服务器之类的。刚好我的VPS服务器上的系统是gentoo,于是就费了点时间写了一个脚本。

首先贴脚本的配置文件:

1
2
3
4
5
6
7
8
# Configuration for /etc/init.d/socat
# File: /etc/socat.conf

SOCAT_ARGS= "-d -d -d  -lf /var/log/socat.log"
AUTOSTART= "wesnoth wesnoth6"

SOCAT_wesnoth= "TCP-LISTEN:15000,reuseaddr,fork,su=nobody TCP4:server.wesnoth.org:15000"
SOCAT_wesnoth6= "TCP6-LISTEN:15001,reuseaddr,fork,su=nobody TCP4:server.wesnoth.org:15000"

然后贴脚本代码,保存的位置当然是 /etc/init.d/socat :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/sbin/runscript
# Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

BIN= /usr /bin /socat
SOCAT_CONF= /etc /socat.conf
SOCAT_ARGS= "-d -d -lf /var/log/socat.log"

[ ! -f $SOCAT_CONF ] || source $SOCAT_CONF
[ -x $BIN ] || exit 0

depend ( ) {
        need net
}

start ( ) {
        ebegin "Starting ${SVCNAME}"

    if test "x$AUTOSTART" = "xnone" -o -z "x$AUTOSTART" ; then
        ewarn "Autostart is set to 'none', so disabled."
        exit 0
    fi

    for FORWARD in $AUTOSTART ; do
        ARGS= ` eval echo \\\ $SOCAT_ $FORWARD `
        PID= "/var/run/${SVCNAME}/$FORWARD.pid"
        start-stop-daemon -b --start --exec ${BIN} --make-pidfile --pidfile "${PID}" -- ${SOCAT_ARGS} ${ARGS} &
    done

        eend $? "Check ${SOCAT_LOG} to see why startup failed"
}

stop ( ) {
        ebegin "Stopping ${SVCNAME}"
    for PID in /var /run / ${SVCNAME} /*.pid; do
        start-stop-daemon --stop --quiet --exec ${BIN} --pidfile "${PID}"
    done
        eend $?
}

# vim: set ts=4 :

接着,配置完/etc/socat.conf后,就可以启动socat服务了:

1
/etc /init.d /socat start

关闭服务的命令是:

1
/etc /init.d /socat stop

当然,我更是直接加入到了boot服务组里了,下次开机时能够自动启动:

1
rc-update add socat boot

好了,大功告成!

不过,依旧有一些问题。例如我首先使用 TCP4-LISTEN:15000 绑定了一个IPv4的TCP监听后,接着使用 TCP6-LISTEN:15000 绑定则会提示失败:

1
2
3
# socat  -d -d  TCP6-LISTEN:15000,reuseaddr,fork,su=nobody TCP4:server.wesnoth.org:15000
2010/09/29 23:19:42 socat[3166] E bind(3, {AF=10 [0000:0000:0000:0000:0000:0000:0000:0000]:15000}, 28): Address already in use
2010/09/29 23:19:42 socat[3166] N exit(1)

可是此时查看网络端口的监听情况,并没有发现IPv6上有监听:

1
2
3
4
5
6
7
# netstat -an | grep LISTEN
tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN    
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN    
tcp        0      0 0.0.0.0:21              0.0.0.0:*               LISTEN    
tcp        0      0 0.0.0.0:15000           0.0.0.0:*               LISTEN    
tcp6       0      0 :::21                   :::*                    LISTEN

真是奇怪呢……可惜手头没有IPv6,难以测试啊……

posted on 2012-12-02 22:46  lexus 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lexus/archive/2012/12/02/2798796.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值