風雲論壇电脑网络 → 浏览:帖子主题
* 帖子主题:通过 ssh 隧道将局域网端口发布到公网的脚本
admin11 (ID: 46)
等级:新手上路
积分:7
发帖:1
来自:保密
注册:2023/11/24 17:42:27
造访:2023/11/24 17:42:27
[ 第 1 楼 ] 回复
需求举例:将局域网中本地的 22、80、3389 等端口发布到公网的 27、80、3389,以便用户访问网站和自己远程管理服务器
前置条件:本地有一台 Linux 系统,公网有一台 Linux 服务器。

原理是使用 while 循环保证服务可用性。流程如下:
1、登录 ssh 服务器,执行 netstat -pant |grep 0.0.0.0:27 ,检查服务端是不是已经有一个 0.0.0.0:27 的侦听了(因为本次连接需要占用服务端 27 端口)。
2、执行完后,如果退出代码($?)不为0,说明可能网络不通,或着其他错误非正常退出来了,那么等待 30 秒后进入下一次循环(重试)
3、使用“LISTEN ”分割 $check,尝试获取进程信息的 \d+/sshd 部分内容
4、尝试从进程信息中取出 进程 pid
5、如果真取到了进程信息,说明 0.0.0.0:27 已经被侦听了,需要结束掉才能重新映射到 27,于是再次登录 ssh 并执行 kill $pid
6、登录 ssh 并将本地 22 端口映射到服务端 0.0.0.0:27。如果连接异常断开了,等待 30 秒后会继续重试,保证服务可用。

注意:使用此脚本前需要先使用 ssh-copy-id 传递本机公钥到服务器上,否则脚本运行过程中会需要手工输密码,导致服务无法继续。
2023/11/24 17:44:11 IP:已设置保密
Rimifon (ID: 1)
头衔:论坛坛主
等级:究级天王[荣誉]
积分:266
发帖:11
来自:保密
注册:2022/3/30 11:18:46
造访:2024/4/11 17:38:14
[ 第 2 楼 ] 回复
下面以本机 22 端口发布到公网服务端 27 端口为例(SSH 服务器假设为:fengyun.org:2322):
#!/bin/sh
user="root"
host="fengyun.org"
port=2322
flag="0.0.0.0:27"    # 用于判断能否将本机 22 发布到服务端 27,如果已经存在则需要关闭
while true; do
    date
    echo '检测服务器状态……'
    # 增加 ; uname 是为了 grep 未匹配到内容导致 $? 值为 1(代表执行异常退出)
    check=$(ssh -p $port $user@$host "netstat -pant |grep $flag; uname")
    if [ $? != 0 ]; then
        echo "连接 $host 失败, 30 秒后重试……"
        sleep 30
        continue
    fi
    proc=$(echo $check |awk -F'LISTEN ' '{print $2}')
    pid=${proc%/*}
    if [ -z $pid ]; then
        echo "$flag 现在是可用的!"
    else
        ssh -p $port $user@$host kill $pid
        echo "进程PID $pid 已经打开了 $flag,干掉他!"
    fi
    echo "正在发布服务到主机 $host ……"
    ssh -p $port -o ServerAliveInterval=30 -N -R 80:127.168.33.51:80 -R 27:127.34.56.78:22 -R 3389:127.17.0.1:3389 $user@$host
    date
    echo "$host 的连接断开了,将在 30 秒后重新尝试连接……"
    sleep 30
done

建议使用 root 账号,其他账号 netstat -pant 可能无法得到进程信息,而且映射到公网的端口必须大于 1024。
2024/4/2 23:30:16 IP:已设置保密
分页: 1, 共 1 页
快速回复主题
账号/密码
用户: 没有注册? 密码:
评论内容