内网穿透反向隧道代理技术 -电脑资料

电脑资料 时间:2019-01-01 我要投稿
【meiwen.anslib.com - 电脑资料】

   

    本文的主要目的是利用使 ssh 服务器(外网)通过客户端(内网)代理上网以及反向控制客户端(内网),不需要网络管理员权限,不需要 NAT,

内网穿透反向隧道代理技术

。即可上网主机 A 位于内网,不可上网主机 B 位于外网,A 能直接访问 B,但 B 无法访问防火墙内的 A,这样 B 就可以使用 SSH 隧道访问 A 主机上的代理服务器上网。(估计有这种变态需求的人只存在于大学中)

    B(210.77.*.*)---->(210.77.*.*)FW(192.168.0.*)|--->(192.168.0.*)A---->(192.168.0.*)FW(123.*.*.*)---->Internet

    B(210.77.*.*)< ----(210.77.*.*)FW(192.168.0.*)-----(192.168.0.*)A<----(192.168.0.*)FW(123.*.*.*)<----Internet

    一、代理

    首先在客户端上安装 socks 代理(HTTP 代理可以使用 Squid,同理)。socks 代理软件使用 Dante。Dante 的启动以及配置需要手动调整,下面是 Dante 的配置文件 /etc/sockd.conf:

compatibility:reuseaddrinternal:0.0.0.0 port = 1080external:eth0logoutput:/var/log/sockd/sockdclientmethod:nonemethod:noneuser.privileged:rootuser.notprivileged:solrexconnecttimeout:60iotimeout:86400## client access rulesclient pass { from: 127.0.0.1/0 port 1-65535 to: 0.0.0.0/0 log: connect disconnect}## server operation access rules#allow bind to ports greater than 1023pass {  from: 0.0.0.0/0 to: 0.0.0.0/0 port gt 1023  command: bind bindreply udpassociate udpreply  log: connect disconnect}pass {  from: 0.0.0.0/0 to: 0.0.0.0/0 port 1-65535  protocol: tcp udp  log: connect disconnect}#allow outgoing connections (tcp and udp)pass {  from: 127.0.0.1/0 to: 0.0.0.0/0  command: bind bindreply connect udpassociate udpreply  log: connect disconnect}#allow replies to bind, and incoming udp packetspass {   from: 0.0.0.0/0 to: 0.0.0.0/0   command: bind bindreply connect udpassociate udpreply   log: connect error}#log the restblock {   from: 0.0.0.0/0 to: 0.0.0.0/0   log: connect error}

    下面是 Dante 的启动脚本 /etc/init.d/sockd:

#!/bin/shset -e. /lib/lsb/init-functions[ -f /usr/local/sbin/sockd ] || exit 0[ ! -f /etc/sockd.conf ] && exit 1SOCKD_CONF="-f /etc/sockd.conf"SOCKD_OPTS="-D"case "$1" in  start)    # Start daemons.    log_daemon_msg "Starting Dante socks proxy server" "sockd"    if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sockd.pid --exec /usr/local/sbin/sockd -- $SOCKD_OPTS; then	    log_end_msg 0	else	    log_end_msg 1	fi    ;;  stop)    # Stop daemons.    log_daemon_msg "Stoping Dante socks proxy server" "sockd"	if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sockd.pid; then	    log_end_msg 0	else	    log_end_msg 1	fi	;;  restart)    log_daemon_msg "Restarting Dante socks proxy server" "sockd"	start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sockd.pid	if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sockd.pid --exec /usr/local/sbin/sockd -- $SOCKD_OPTS; then	    log_end_msg 0	else	    log_end_msg 1	fi	;;  *)    log_action_msg "Usage: /etc/init.d/sockd {start|stop|restart}\n"    exit 1esacexit 0

    二、ssh 服务器

    服务器端 ssh 服务器最好采用 Openssh,Windows 下应该使用 Cygwin 运行 sshd,FreeSSHd 实践证明崩溃比较频繁,

电脑资料

内网穿透反向隧道代理技术》(http://meiwen.anslib.com)。同一台机器的 Windows 和 Linux 上运行的 ssh 服务器最好使用相同的 host key,将 /etc/ssh/ 下面的文件保持一致即可。最好配置服务器为使用公钥进行登录验证,这样能使用自动脚本进行端口映射。

    三、手动建立隧道(客户端到服务器端口映射)

用下面命令建立客户端到服务器的端口映射,将客户端的 socks 代理端口 1080 映射到服务器的端口 8080。这样服务器就可以通过自己的 8080 端口反向隧道到客户端的 socks 代理 1080 端口上网。

    ssh -C -f -N -g -o PreferredAuthentications=publickey -R SERVER:8080:127.0.0.1:1080 USRNAME@SERVER

    # 参数含义:

    # -C: 要求对数据进行压缩

    # -f:要求 ssh 执行完交互后进入后台运行

    # -N:不用建立一个终端

    # -g:允许远程服务器连接客户端转发端口

    # -R SERVER:8080:127.0.0.1:1080:将客户机(127.0.0.1)的 1080 端口绑定到服务器(SERVER)的 8080 端口。

    # USRNAME@SERVER:ssh服务器的用户名和密码

    # -p 3022:ssh服务器的端口

    为了方便控制,最好也将客户端的 ssh 服务器端口映射到服务器端,服务器端就可以通过登录自己的 8022 端口来登录客户端的 ssh 服务器:

    ssh -C -f -N -g -o PreferredAuthentications=publickey -R SERVER:8022:127.0.0.1:22 USRNAME@SERVER

    这样两台被防火墙隔开的主机就能实现双向控制。

    四、自动建立隧道

    手动建立隧道的缺陷是服务器端必须长期开机,并且连接只能用户在客户端手动发起。可以考虑间接的办法,比如使用两台主机均可访问的服务器作为跳板,或者客户端自动登录聊天软件,利用聊天软件接受指令。下面给出一种使用共享服务器的方法:

#!/bin/bash# {start|stop|restart:username:ipaddress}COMMAND="stop"SERVER="0.0.0.0"USRNAME=""PORT="22"INFOURL="http://someserver.com/somepage"SSHOPTS="-C -f -N -g -o PreferredAuthentications=publickey -o StrictHostKeyChecking=no"get_server_info(){  #info=`wget -nv -O - $INFOURL 2> /dev/null | iconv -f gbk -t utf8 |        grep -o -e "{.*}" | tr -d '{}'`  info=`wget -nv -O - $INFOURL 2> /dev/null | iconv -f gbk -t utf8 |        sed -n "/{*}/s/.*{\(.*\)}.*/\1/p"`  COMMAND=${info%%:*}  SERVER=${info#*:}  USRNAME=${SERVER%:*}  SERVER=${SERVER#*:}}tunneling_status(){  tun_ps=`ps aux | grep "ssh -C" | wc -l`  if [ $tun_ps -gt 4 ]; then    echo -n "running"  else    echo -n "died"  fi}start_tunneling(){  ssh $SSHOPTS -R 3128:127.0.0.1:3128 ${USRNAME}@${SERVER} -p $PORT  ssh $SSHOPTS -R 8022:127.0.0.1:22 ${USRNAME}@${SERVER} -p $PORT}failsafe_tunneling(){  ssh $SSHOPTS -R 8022:127.0.0.1:22 ${USRNAME}@${SERVER} -p $PORT}stop_tunneling(){  killall -e ssh}echo -n "[`date +%F\ %R`] "get_server_infocase "$COMMAND" in  start)    if [ $(tunneling_status) = "running" ]; then      echo "Starting ssh tunneling.(started, do nothing)"    else      echo "Starting ssh tunneling."      start_tunneling    fi    ;;  restart)    if [ $(tunneling_status) = "running" ]; then      echo "Restarting ssh tunneling."      stop_tunneling      start_tunneling    else      echo "Restarting ssh tunneling."      start_tunneling    fi    ;;  stop)    if [ $(tunneling_status) = "running" ]; then      echo "Stoping ssh tunneling."      stop_tunneling    else      echo "Stoping ssh tunneling.(stoped, do nothing)"    fi    ;;  failsafe)    echo "Starging ssh tunneling.(failsafe mode)"    failsafe_tunneling    ;;  sleep)    echo "Sleeping."    exit 0    ;;  *)    echo "Unrecogenized server command ($COMMAND)."    exit 1    ;;esacexit 0

    将上面脚本加入 crontab 每十分钟运行一次,就能实现在服务器端对客户端进行有限的控制。

    ​

最新文章