Ssh

如何製作基於 ssh 的 vpn?

  • January 22, 2021

我在製作基於 ssh 的 VPN 時遇到了一些問題。

情況:

LOCAL ->            GATE                 -> SERVICES 
               (ssh server)     (Many other servers with some services)
192.168.0.10     10.1.0.154             172.26.106.0/24
255.255.255.0    255.255.0.0

從 LOCAL 我可以通過 ssh 登錄到 GATE,然後從這裡我可以訪問所有 SERVICES 伺服器。

但是我想直接從我的本地電腦訪問服務。我怎樣才能做到這一點?

這是我在閱讀 ssh 手冊後嘗試做的事情:

在本地:

# ssh -f -w 1:2 root@GATE true
# ifconfig tun1 10.66.1.1 10.66.1.2 netmask 255.255.255.252
# route add -net 172.26.106.0 netmask 255.255.255.0 gw 10.66.1.2 

在門上:

# ifconfig tun2 10.66.1.2 10.66.1.1 netmask 255.255.255.252

它不起作用。當我嘗試從 LOCAL SSH 到某些 SERVICE 時出現超時;-(

距離我提出這個問題還有兩年半的時間……現在我找到了另一個非常簡單的解決方案。您可以只使用名為sshuttle.

sshuttle手冊:

sshuttle 允許您創建從您的機器到可以通過 ssh 連接的任何遠端伺服器的 VPN 連接,只要該伺服器具有 python 2.3 或更高版本。

IE:

sshuttle -r user@gate 172.26.100.0/24 172.26.106.0/24 172.26.103.0/24

然後在另一個終端中,您可以直接從路由子網對任何伺服器執行 ssh:

IE:

ssh xyz@172.26.100.1

感謝 Jeff Meden 的評論,我設法做到了。我根據我的需要調整了該腳本: github.com/oicu/vpn-over-ssh/blob/master/svpn.sh,最後它起作用了:

我的版本:

#!/bin/bash
PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
export PATH

[ "$(whoami)" != 'root' ] && echo "Run it as root." && exit 1

SERVER_SSH_PORT="22"
SERVER_SSH_IP="10.1.0.154"
CLIENT_TUNNEL="tun5"
SERVER_TUNNEL="tun4"
CLIENT_TUN_IP="192.168.55.5"
SERVER_TUN_IP="192.168.55.4"
TUN_NETMASK="255.255.255.0"
CLIENT_ETHERNET="enp12s0"
SERVER_ETHERNET="eth0"
ROUTES=("172.26.100.0/24" "172.26.106.0/24" "172.26.103.0/24")


function start() {
   ssh -NTCf -w "${CLIENT_TUNNEL#tun}:${SERVER_TUNNEL#tun}"  root@${SERVER_SSH_IP} -p ${SERVER_SSH_PORT}
   if [ $? -ne 0 ]; 
       then exit 1; 
   fi
   echo "ssh tunnel is working."
   ssh -T root@${SERVER_SSH_IP} -p ${SERVER_SSH_PORT}  << eeooff
       ifconfig ${SERVER_TUNNEL} ${SERVER_TUN_IP} pointopoint ${CLIENT_TUN_IP} netmask ${TUN_NETMASK}
       iptables -t nat -A POSTROUTING -s ${CLIENT_TUN_IP}/32 -o ${SERVER_ETHERNET} -j MASQUERADE
       iptables -A FORWARD -p tcp --syn -s ${CLIENT_TUN_IP}/32 -j TCPMSS --set-mss 1356
       exit
eeooff

   for ROUTE in ${ROUTES[*]}
   do
       ssh -T root@${SERVER_SSH_IP} -p ${SERVER_SSH_PORT} "iptables -t nat -A POSTROUTING -s $ROUTE -o ${CLIENT_TUNNEL} -j MASQUERADE"
   done


   if [ $? -ne 0 ]; 
       then exit 1; 
   fi
   echo "remote start."
   ifconfig ${CLIENT_TUNNEL} > /dev/null 2>&1
   if [ $? -eq 0 ]; then
       echo 1 > /proc/sys/net/ipv4/ip_forward
       ifconfig ${CLIENT_TUNNEL} ${CLIENT_TUN_IP} pointopoint ${SERVER_TUN_IP} netmask ${TUN_NETMASK}

       for ROUTE in ${ROUTES[*]}
       do
           ip route add $ROUTE via ${CLIENT_TUN_IP} metric 102
           printf "Adding route: %s\n" $ROUTE
       done

       iptables -t nat -A POSTROUTING -s ${SERVER_TUN_IP}/32 -o ${CLIENT_ETHERNET} -j MASQUERADE
       iptables -A FORWARD -p tcp --syn -s ${SERVER_TUN_IP}/32 -j TCPMSS --set-mss 1356
       for ROUTE in ${ROUTES[*]}
       do
           iptables -t nat -A POSTROUTING -s $ROUTE -o ${CLIENT_TUNNEL} -j MASQUERADE
       done


       ping ${SERVER_TUN_IP} -i 60 > /dev/null 2>&1 & echo "local start."
   else
       exit 1
   fi
}


function  stop(){
   echo "Flushing iptables on server..."
   ssh -T root@${SERVER_SSH_IP} -p ${SERVER_SSH_PORT} "iptables -F"

   echo "Flushing iptables on localhost..."
   iptables -F

   echo "Killing ssh tunnel..."
   CLIENT_SSH_PID=`ps -ef | grep "ssh -NTCf -w ${CLIENT_TUNNEL#tun}:${SERVER_TUNNEL#tun}" | grep -v grep | head -n1 | awk '{print $2}'`
   if [ -n "${CLIENT_SSH_PID}" ]; then 
       kill -9 ${CLIENT_SSH_PID}
   fi
   if [ -n "`pidof ping`" ]; then 
       pidof ping | xargs kill -9 
   fi
}

function usage(){
   echo "usage:"
   echo "    $0 -start"
   echo "    $0 -stop"
   echo ""
   echo "for ssh:"
   echo "    nohup $0 -start > /dev/null 2>&1"
}

case $1 in
   "--start" | "-start")
       start
       ;;
   "--stop" | "-stop")
       stop
       ;;
   *)
       usage
       ;;
esac

引用自:https://serverfault.com/questions/782220