客服电话
17728153743本文的主要目的是利用使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:reuseaddr
internal:0.0.0.0 port=1080
external:eth0
logoutput:/var/log/sockd/sockd
clientmethod:none
method:none
user.privileged:root
user.notprivileged:solrex
connecttimeout:60
iotimeout:86400
##client access rules
client 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 1023
pass{
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 packets
pass{
from:0.0.0.0/0 to:0.0.0.0/0
command:bind bindreply connect udpassociate udpreply
log:connect error
}
#log the rest
block{
from:0.0.0.0/0 to:0.0.0.0/0
log:connect error
}
下面是Dante的启动脚本/etc/init.d/sockd:
#!/bin/sh
set-e
./lib/lsb/init-functions
[-f/usr/local/sbin/sockd]||exit 0
[!-f/etc/sockd.conf]&&exit 1
SOCKD_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 1
esac
exit 0
二、ssh服务器
服务器端ssh服务器最好采用Openssh,Windows下应该使用Cygwin运行sshd,FreeSSHd实践证明崩溃比较频繁。同一台机器的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-oPreferredAuthentications=publickey-oStrictHostKeyChecking=no"
get_server_info()
{
#info=`wget-nv-O-$INFOURL2>/dev/null|iconv-fgbk-tutf8|
grep-o-e"{.*}"|tr-d'{}'`
info=`wget-nv-O-$INFOURL2>/dev/null|iconv-fgbk-tutf8|
sed-n"/{*}/s/.*{\(.*\)}.*/\1/p"`
COMMAND=${info%%:*}
SERVER=${info#*:}
USRNAME=${SERVER%:*}
SERVER=${SERVER#*:}
}
tunneling_status()
{
tun_ps=`psaux|grep"ssh-C"|wc-l`
if[$tun_ps-gt4];then
echo-n"running"
else
echo-n"died"
fi
}
start_tunneling()
{
ssh$SSHOPTS-R3128:127.0.0.1:3128${USRNAME}@${SERVER}-p$PORT
ssh$SSHOPTS-R8022:127.0.0.1:22${USRNAME}@${SERVER}-p$PORT
}
failsafe_tunneling()
{
ssh$SSHOPTS-R8022:127.0.0.1:22${USRNAME}@${SERVER}-p$PORT
}
stop_tunneling()
{
killall-essh
}
echo-n"[`date+%F\%R`]"
get_server_info
case"$COMMAND"in
start)
if[$(tunneling_status)="running"];then
echo"Startingsshtunneling.(started,donothing)"
else
echo"Startingsshtunneling."
start_tunneling
fi
;;
restart)
if[$(tunneling_status)="running"];then
echo"Restartingsshtunneling."
stop_tunneling
start_tunneling
else
echo"Restartingsshtunneling."
start_tunneling
fi
;;
stop)
if[$(tunneling_status)="running"];then
echo"Stopingsshtunneling."
stop_tunneling
else
echo"Stopingsshtunneling.(stoped,donothing)"
fi
;;
failsafe)
echo"Stargingsshtunneling.(failsafemode)"
failsafe_tunneling
;;
sleep)
echo"Sleeping."
exit0
;;
*)
echo"Unrecogenizedservercommand($COMMAND)."
exit1
;;
esac
exit0