[原创]用 SSH 转发和 Nginx 反向代理

Posted on 2020-07-22

先说说 SSH 的本地转发和远程转发,也叫作正向转发和反向转发。

  • 本地转发:内网机器(Client)SSH连接到外网机器(Server),内网机器监听本地指定端口,并将该端口的所有数据转发到外网机器的指定端口。方向是本地到远端。SSH 使用 -L 参数。

命令格式:

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
  • 远程转发:内网机器(Client)SSH连接到外网机器(Server),内网机器要求外网机器监听指定端口,并将该端口的所有数据转发到内网机器的指定端口。方向是远端到本地。SSH 使用 -R 参数。

命令格式:

ssh -R <local port>:<remote host>:<remote port> <SSH hostname>


注意:上边虽然以内网机器和外网机器来区分 Client 端和 Server 端,是方便在最容易的情况下理解其工作方式。并不一定是内网的机器或外网的机器,也可能全是外网机器,但是由于策略或者防火墙因素导致无法访问其中某一个,而需要另外一个来作为跳板转发。


下来就是实战。

安装 sshpass 免密码登录 ssh,或者使用证书免密码登录。

apt install sshpass

实现后台连接 ssh,开启远程转发

sshpass -p "112233aabbcc" ssh -CNfg -R 8080:127.0.0.1:80 -R 4433:127.0.0.1:443 -R 2211:127.0.0.01:22 root@1.1.1.1

一次开启了3个转发端口

本地端口(Client)

远程端口(Server)

127.0.0.1:80 ←→ 1.1.1.1:8080

127.0.0.1:443 ←→ 1.1.1.1:4433

127.0.0.1:22 ←→ 1.1.1.1:2211


打开 SSH 转发之前,在 1.1.1.1 (Server) 上查看端口,可以看见只监听了 22 端口

# netstat -ntpl
激活Internet连接 (仅服务器)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      983/sshd
tcp6       0      0 :::22                   :::*                    LISTEN      983/sshd


打开 SSH 转发之后,再查看 1.1.1.1 (Server)  上的端口,可以看见多了3个监听端口

# netstat -ntpl
激活Internet连接 (仅服务器)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1244/sshd: root
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      983/sshd
tcp        0      0 0.0.0.0:4433            0.0.0.0:*               LISTEN      1244/sshd: root
tcp        0      0 0.0.0.0:2211            0.0.0.0:*               LISTEN      1244/sshd: root
tcp6       0      0 :::8080                 :::*                    LISTEN      1244/sshd: root
tcp6       0      0 :::22                   :::*                    LISTEN      983/sshd
tcp6       0      0 :::4433                 :::*                    LISTEN      1244/sshd: root
tcp6       0      0 :::2211                 :::*                    LISTEN      1244/sshd: root


注意:远程转发的 Server 端默认只监听 127.0.0.1 地址上的端口,如果要监听在 0.0.0.0 上,需要在 Server 端需要修改 /etc/ssh/sshd_config 文件,添加一行配置:

GatewayPorts yes

因为 SSH 默认配置出于安全考虑,远程转发是只用于 Server 端自身发起访问请求的,如果跟本例一样,前边还有一个 Nginx 做反向代理的话,就不用修改 SSH 配置了。如果是反向转发之后直接使用的,就需要修改配置文件,监听在 0.0.0.0 上了。


说明端口转发已经开始工作了,我们可以通过 1.1.1.1:222 这个Server的地址 SSH 登录到 Client 端了。

同时可以从 http://1.1.1.1:8080 和 https://1.1.1.1:4433 访问到 Client 的 Web 服务。


为什么反向转发要监听 8080 和 4433 呢,直接监听 80 和 443 不就可以用了,何必多此一举,再开一个 Nginx 反向代理 80 到 8080 ,4433 到 443 呢,因为如果没有 Nginx 的话,在 Client 上获取客户端 IP 永远是 127.0.0.1,有需要 Client IP 的应用就无法拿到正确的 IP 了。


下面就是安装 Nginx

apt-get update && apt-get install -y gnupg2
sh -c "echo 'deb http://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx' > /etc/apt/sources.list.d/nginx.list"
wget -O - http://nginx.org/keys/nginx_signing.key | apt-key add -
apt update
apt install nginx


Nginx 反向代理配置

user  nginx;
worker_processes  1;
 
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
events {
    worker_connections  1024;
}
 
 
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log  /var/log/nginx/access.log  main;
 
    sendfile        on;
    #tcp_nopush     on;
 
    keepalive_timeout  65;
 
    gzip  on;
 
    #include /etc/nginx/conf.d/*.conf;
 
    server {
        listen 443 ssl;
        ssl on;
        ssl_certificate     server.pem;
        ssl_certificate_key server.key;
        location / {
                proxy_pass https://127.0.0.1:4433;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto  $scheme;
                proxy_redirect     off;
        }
    }
 
    server {
        listen 80;
        location / {
                proxy_pass http://127.0.0.1:8080;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}
 
stream {
    server {
        listen 222;
        proxy_connect_timeout 30s;
        proxy_timeout 600s;
        proxy_pass 127.0.0.1:2211;
    }
}

反向代理 Web 服务的 0.0.0.0:80 到 127.0.0.1:8080,0.0.0.0:443 到 127.0.0.1:4433

反向代理 TCP 的 0.0.0.0:222 到 127.0.0.1:2211


OK,大功告成,内网机器上的 Web 可以从外网访问了,同时也能获取正确的 Client IP 了,通过外网也能 SSH 登录内网机器了。


最后,再写个脚本,如果 SSH 断开了就自动重连,嗯,6 秒检查一次。

#cat /root/SSHPortforwarding.sh
#!/bin/bash
while [ true ]
do
	vpn=`ps aux|grep -E 'ssh \-' |wc -l`
	if [ $vpn -lt 1 ]; then
		sshpass -p "112233aabbcc" ssh -CNfg -R 8080:127.0.0.1:80 -R 4433:127.0.0.1:443 -R 2211:127.0.0.01:22 root@1.1.1.1
	fi
	sleep 6
done

再把这个脚本放到 rc.local 里,开机自动启动。

nohup bash /root/SSHPortforwarding.sh > /var/log/SSHPortforwarding.log 2>&1 &

 评论
张三
orz
李四
orz orz
李小四
orz orz orz
张小三
orz orz orz orz
  搜索
  Tags
全部   Ubuntu   Linux   Python   Windows   Shell   转发   字体   循环   js   KMS   MySQL   html   DNS   css   多线程   VSCode   Office   安装   WinSCP   字典   原创   多进程   反向代理   领带   截取字符   随机数   随机   重定向   远程调试   进程池   进度条   网卡   线程池   电源   生活   激活   浏览器   日志   数据库   venv   vbs   uuid   IP   iostat   import   GitHub   dpkg   DHCP   curl   crx   CPU   cloud-init   BBR   Apt   iptables   Kitsunebi   kvm   tc   subprocess   SSH   SoftEther   Set   samba   pyflakes   pip   Nginx   NextCloud   List   libreoffice   Adobe  
  功能
You can put anything you want inside of these side widgets. They are easy to use, and feature the new Bootstrap 4 card containers!