已有远程有独立 IP 的服务器,实现本地 Linux 电脑内网穿透

若已有远程有独立 IP 的服务器,可以使用 SSH 反向隧道的方式实现本地 Linux 电脑内网穿透。以下是具体的步骤:

本地电脑设置

在本地 Linux 电脑上设置 SSH 服务,开启 SSH 服务监听端口,默认情况下为 22 端口。

远程独立 IP 服务器设置

在远程服务器上安装 SSH 服务,并开启 SSH 服务监听端口,默认情况下为 22 端口。确保能够从服务器上 SSH 登录本地 Linux 电脑。

流量转发

在本地 Linux 电脑上通过 SSH 命令将流量转发到远程服务器上:

   ssh -N -R 0.0.0.0:2222:localhost:22  {remoteuser}@{remoteip}

其中:remoteuser 是远程服务器的用户名,remoteip 是远程服务器的 IP 地址。上述命令将本地 Linux 电脑的 22 端口 (localhost:22) 转发到远程服务器的 2222 端口 (0.0.0.0:2222)。

远程访问本地

通过上一步的流量转发后即可在远程服务器连接到本地 Linux 电脑:

   ssh -p 2222  {localuser}@localhost

其中:localuser 是本地 Linux 电脑的用户名。

其他端口穿透

如果需要其他应用的内网穿透,可将其端口号加入到转发命令中。

   ssh -N -R 0.0.0.0:8080:localhost:80  {remoteuser}@{remoteip}

将本地 Linux 电脑的 80 端口转发到远程服务器的 8080 端口。

上述操作可以实现本地 Linux 电脑的内网穿透,可以通过远程服务器访问本地 Linux 电脑上的应用和服务。注意确保远程服务器的安全性,并适当设置防火墙规则。

使用 autossh 做转发

相比于 ssh, autossh 可以在网络断开后自动重新连接,保证了服务的稳定性。

在本地电脑上安装 autossh

sudo apt-get update
sudo apt-get install autossh

流量转发

在本地机器上建立 SSH 连接,并使用 autossh 将服务器上的端口映射到本地机器的端口。其中,remote_port 是服务器上的端口号,local_port 是本地机器上的端口号。

autossh -M 2223 -R remote_port:localhost:local_port  -o ServerAliveInterval=15 {remoteuser}@{remoteip}

参数说明

-M 参数表示指定一个监控端口,如果连接断开就会自动重连;
-o 参数用于指定SSH连接选项,这里设置了每隔15秒发送一次心跳包以保持连接;
-N 参数表示建立一个不执行远程命令的SSH连接;
-R 参数用于指定端口转发规则,这里表示将公网服务器的2222端口映射到目标机器的22端口;
最后的{remoteuser}@{remoteip}表示登录目标机器的用户名和IP地址

执行以上命令后,SSH 连接会一直保持开启,在服务器上访问 localhost:remote_port 即可访问到本地机器上的服务。

通过 supervisor 实现开机自启、终止自启

[program:autossh22]
command                 = autossh -N -R 0.0.0.0:2222:localhost:22 -o ServerAliveInterval=15 -i ~/.ssh/id_rsa remoteuser@remoteip
user=wml
process_name            = %(program_name)s_%(process_num)s
numprocs                = 1
autostart               = true
autorestart             = true
startretries            = 1000 ; 启动失败自动重试次数,默认是 3, 把这个值调大点,防止redis长时间连不上的情况(如之前遇到的主备切换长时间连不上)
stdout_logfile          = /alidata/log/supervisor/autossh22.log
stdout_logfile_maxbytes = 100MB
redirect_stderr=true

[program:autossh80]
command                 = autossh -N -R 0.0.0.0:2280:localhost:80 -o ServerAliveInterval=15 -i ~/.ssh/id_rsa remoteuser@remoteip
user=wml
process_name            = %(program_name)s_%(process_num)s
numprocs                = 1
autostart               = true
autorestart             = true
startretries            = 1000 ; 启动失败自动重试次数,默认是 3, 把这个值调大点,防止redis长时间连不上的情况(如之前遇到的主备切换长时间连不上)
stdout_logfile          = /alidata/log/supervisor/autossh80.log
stdout_logfile_maxbytes = 100MB
redirect_stderr=true

在外网通过域名访问本地 Linux 电脑服务

可以在远程服务端用 nginx 做服务转发,如 配置远程端口 2280 转发到本地服务器 80, nginx 配置如下

upstream home{
    server 127.0.0.1:2280;
}

server {
    listen 80;
    listen [::]:80;
    server_name test.com;
    server_tokens off;

    auth_basic "请输入账号密码";   #这里是验证时的提示信息
    auth_basic_user_file /alidata/data/auth_basic/ip_passwdfile;

    index index.html index.htm index.php default.html default.htm default.php;

    charset utf-8;

    error_page 404 /index.php;

    location /
        {
            proxy_pass http://home;
            proxy_set_header Host $host:$server_port;
        }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log  /alidata/log/nginx/test.com.log main;
    error_log  /alidata/log/nginx/nginx_error.log;

}

本地机器重启导致 autossh 断开问题

当本地机器重启后虽然通过 supervisor 重新启动了 autossh, 但可能会报错Warning: remote port forwarding failed for listen port 2222,发现远程服务器的 2222 端口被占用,需要杀掉进程

# 运行该命令查看占用端口的进程id

sudo netstat -plant  | grep 2222

# 杀掉该进程

sudo kill -9  {pid}

之后再来本地重新执行 autossh 命令即可