SYNOPSIS
ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-E log_file] [-e escape_char]
[-F configfile] [-I pkcs11] [-i identity_file]
[-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]
[-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]
[-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]
[user@]hostname [command]
ssh支持動態端口轉發,由ssh來判斷發起請求的工具使用的是什么應用層協議,然后根據判斷出的協議結果決定目標端口。
以下圖為例進行說明,host1處在辦公內網,能和host3互相通信,但它無法直接和互聯網和host2通信,而host3則可以和host2以及互聯網通信

要讓host1訪問互聯網,又能和host2的22端口即ssh服務通信,顯然在host1上僅設置一個本地端口轉發是不夠的。使用動態端口轉發即可
語法格式為:
ssh -D [bind_addr:]port hostname
以上圖為例,在host1上執行:
[root@xuexi ~]# ssh -Nfg -D 2222 host3
執行完上面的命令,host1將在本地開啟SOCKS4或SOCKS5服務來監聽2222端口。只要客戶端程序工具(隱含了使用的應用層協議類型)將其自身的代理設置為host1:2222,則該程序所有產生的數據都將轉發到host1:2222,再由host1:2222將數據通過隧道轉發給host3,最后由host3和互聯網或host2上對應客戶端工具的應用層協議的端口進行通信。
Refence: https://www.cnblogs.com/f-ck-need-u/p/10482832.html
使用ssh動態端口轉發實現FQ腳本如下:
shell腳本如下:
vim sockstunnel.sh
#!/bin/bash
if [ -z $1 ];then
echo "No SSH host specified"
exit 1;
fi
SSHCMD="ssh -qCTfnN -D $INTERNEL_IP:$INTERNEL_PORT $1"
CODE=`curl -o -I --connect-timeout 10 -s -w "%{http_code}" https://www.google.com --socks5-host $INTERNEL_IP:$INTERNEL_PORT`
PID=`ps -A -o pid,cmd|grep "$SSHCMD" | grep -v grep |head -n 1 | awk '{print $1}'`
function sshHK() {
echo "`date +%F" "%H:%M:%S` Status: $CODE."
if [ $CODE -ne 200 -a $CODE -ne 302 ];then
if [ -n $PID ];then
kill -9 $PID
echo "`date +%F" "%H:%M:%S` Killed PID: $PID."
fi
echo "`date +%F" "%H:%M:%S` Try to reconnect."
$SSHCMD
return 1
else
return 1
fi
}
sshHK
bash sockstunnel.sh hk #執行腳本需要傳入一個參數(傳入的參數hk,其實對應的是要連接遠程主機ssh hk。在.ssh/config配置中hk對於的就是一台遠程主機),這個參數對應的是要連接遠程主機hostname(本地需要連接這個遠程主機即代理主機,通過這個代理主機連上國外的主機),這個國外的主機是能夠訪問google的。
python腳本如下:
vim ssh_socks_tunnel.py
import sys
import os
import time
if(len(sys.argv) != 2):
print("命令行參數不符合,必須是這樣的",sys.argv[0]+" ""參數1")
exit()
ip="hostname -I | awk '{print $1}'"
internet_ip=os.popen(ip).read().split("\n")[0]
internet_port=6060
cmd_args1=sys.argv[1]
ssh_cmd=f"ssh -qCTfnN -D {internet_ip}:{internet_port} {cmd_args1}"
print("0000",ssh_cmd)
http_code="%{http_code}"
code=f"curl -o -I --connect-timeout 10 -s -w {http_code} https://www.google.com --socks5-host {internet_ip}:{internet_port}"
result_code=os.popen(code).read().split("\n")[0]
print(result_code,type(result_code),"1212")
p1='{print $1}'
pid=f"ps -A -o pid,cmd|grep {internet_port} | grep -v grep |head -n 1 | awk '{p1}'"
result_pid=os.popen(pid).read().split("\n")[0]
print(result_pid,type(result_pid),"1212")
kill_cmd = f"kill -9 {result_pid}"
'''
ubuntu_name="root"
ip_ubuntu="192.168.1.120"
#ssh_cmd="ssh %s@%s 'hostname'"%(ubuntu_name,ip_ubuntu)
ssh_cmd=f"ssh {ubuntu_name}@{ip_ubuntu} 'hostname'"
print(ssh_cmd)
'''
def sshHK():
current_fromt=time.strftime("%Y-%m-%d %H:%M:%S")
print(current_fromt,result_code)
time.sleep(2)
if result_code != 200 and result_code != 302:
print(current_fromt,result_pid)
if len(result_pid) > 0:
os.popen(kill_cmd).read().split("\n")[0]
os.popen(ssh_cmd).read().split("\n")[0]
return
print(current_fromt,result_pid)
os.popen(ssh_cmd).read().split("\n")[0]
else:
return
sshHK()
python3.6 ssh_socks_tunnel.py hk
vim ssh_socks_tunnel1.py
import sys
import subprocess
import time
if(len(sys.argv) != 2):
print("命令行參數不符合,必須是這樣的",sys.argv[0]+" ""參數1")
exit()
def subprocess_Popne(cmd_args):
obj=subprocess.Popen(cmd_args,shell=True,universal_newlines=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
result=obj.stdout.read().split("\n")[0]
return result
def defin_time_front():
current_time=time.strftime("%Y-%m-%d %H:%M:%S")
return current_time
ip="hostname -I | awk '{print $1}'"
internet_ip=subprocess_Popne(ip)
internet_port=6060
cmd_args1=sys.argv[1]
ssh_cmd=f"ssh -qCTfnN -D {internet_ip}:{internet_port} {cmd_args1}"
print("0000",ssh_cmd)
http_code="%{http_code}"
code=f"curl -o -I --connect-timeout 10 -s -w {http_code} https://www.google.com --socks5-host {internet_ip}:{internet_port}"
result_code=subprocess_Popne(code)
print(result_code,type(result_code),"1212")
p1='{print $1}'
pid=f"ps -A -o pid,cmd|grep {internet_port} | grep -v grep |head -n 1 | awk '{p1}'"
result_pid=subprocess_Popne(pid)
print(result_pid,type(result_pid),"1212")
kill_cmd = f"kill -9 {result_pid}"
'''
ubuntu_name="root"
ip_ubuntu="192.168.1.120"
#ssh_cmd="ssh %s@%s 'hostname'"%(ubuntu_name,ip_ubuntu)
ssh_cmd=f"ssh {ubuntu_name}@{ip_ubuntu} 'hostname'"
print(ssh_cmd)
'''
def sshHK():
t=defin_time_front()
print(t,result_code)
if result_code != "200" and result_code != "302":
print(defin_time_front(),result_pid)
if len(result_pid) > 0:
print("進程號!")
#subprocess.call(kill_cmd,shell=True)
subprocess_Popne(kill_cmd)
subprocess_Popne(ssh_cmd)
#subprocess.call(ssh_cmd,shell=True)
return
print(t,result_pid)
subprocess_Popne(ssh_cmd)
#subprocess.call(ssh_cmd,shell=True)
else:
t=defin_time_front()
print(t,"current code:",result_code)
sshHK()
python3.6 ssh_socks_tunnel1.py hk
A 192.168.1.102 客戶端
hk 114.67.xxx.xx 跳板機 #遠程主機即代理主機
C 8.210.x.x 服務器 #國外服務器
以下在客戶端配置ssh別名即通過代理機制實現連接
vim .ssh/config
Host C
HostName 8.210.x.x
User root
Host hk
HostName 114.67.x.x
User root
#代理機制
#proxycommand ssh -W %h:%p C
proxycommand ssh -W 114.67.x.x:22 C
