文章目录
情景描述
之前在校园网内的服务器上部署了web项目,由于外网无法访问到该网站,所以使用frp内网穿透工具借助阿里云服务器代理,从而实现了外网访问该网站。但由于学校网络中心尽职尽责,检测到了我们的frp连接,说我们被黑客黑了,呵呵,并屏蔽掉了我们的公网ip。frp方式会被检测到,不得不寻找其他方法。
一种实测可行的方案是建立云服务器与内网服务器之间的ssh连接,通过ssh传输数据,从而实现内网穿透。目前还不确定能否被网络中心误判为“黑客程序”。
准备工作
1. 服务器示例
机器代号 | 服务器类别 | ip | 用户名 | 本机的ssh 端口号 |
---|---|---|---|---|
A | 内网服务器 | 192.168.1.1 | user_nei | 22 |
B | 公网(云)服务器 | 100.100.100.100 | user_gong | 22 |
注意:上表提供的端口请保证不被防火墙挡住,保证云服务器端口已添加到安全组。一般国内云服务器(如阿里云)需要提前在官网后台添加安全组规则,以开放该端口。
为安全起见,建议不要直接使用root用户去做下文的操作,新建一个权限比较低的普通用户。
2. ssh工具
apt install openssh-server
service ssh restart
反向代理 ssh -fCNR
,我们要在内网服务器上用的。
正向代理 ssh -fCNL
,根据需要使用。
-f 后台执行ssh指令
-C 允许压缩数据
-N 不执行远程指令
-R 将远程主机(服务器)的某个端口转发到本地主机指定的端口
-L 将本地机(客户机)的某个端口转发到远端指定机器的指定端口
-p 指定远程主机的端口
3. autossh工具(重要)
上一节的ssh
工具虽然可以后台运行,但一旦断开了连接,则不会尝试重连!而autossh
恰好可以解决这个问题,在网络不稳定时,ssh
连接可能会断开,而autossh
则会尝试自动重连!
- 安装
apt install autossh
- 如何代替
ssh
?
直接将命令ssh
,替换为
其中autossh -M 8999
8999
端口负责监视连接状态,连接有问题时就会自动重连。
4. ssh免密登录
- 在内网A机器生成秘钥
~/.ssh/id_rsa
和公钥~/.ssh/id_rsa.pub
。一直按Enter
默认就行。ssh-keygen
- 将公钥发送到远程公网B机器。(内网A机器的
~/.ssh/id_rsa.pub
会被写入公网B机器的~/.ssh/authorized_keys
中)
以后在内网A机器执行ssh-copy-id user_gong@100.100.100.100
ssh
(或autossh
)命令访问远程B机器时无需输入密码。
5. 开机自启动
需要注意的是,下文即将提出的方法中,ssh
(或autossh
)命令只是启动了一个进程。一旦服务器关机或重启,进程将丢失,再次开机时,我们需要重新创建一次ssh连接。
由于linux版本的不同,开机自启动的方法不尽相同,请根据自己的系统,搜索开机自启动方法。针对下文提到的方法,我们只需要把ssh
(或autossh
)开头的命令加入到开机自启动项即可。
一、基于ssh+nginx实现外网访问内网的web网站
假设内网服务器运行的网站使用8000
端口访问。
1. 内网服务器:建立反向代理
-
建立内网服务器
8000
端口与公网服务器8001
端口之间的ssh连接ssh -fCNR 8001:localhost:8000 -o ServerAliveInterval=60 user_gong@100.100.100.100 -p 22 # ssh -fCNR [公网IP(可省略)]:[公网端口]:[内网IP]:[内网端口] [公网用户名@公网IP] -p [公网ssh端口(默认22)] # 或者使用autossh: # autossh -M 8999 -CNR 8001:localhost:8000 user_gong@100.100.100.100 -p 22
解释:
-o ServerAliveInterval=60
表示每60秒发送一次消息,以保持连接存在。 -
执行
ps aux | grep ssh
可查看是否成功启动了该进程。
2. 公网服务器
查看是否成功建立了连接
netstat -antpul | grep 8001
可以看到成功建立了连接:127.0.0.1:8001
,这代表只允许本机访问。
3. 公网服务器:配置nginx
由于上面建立的连接端口8001
只允许本机访问,我们需要使用nginx将http(s)
请求都转发到8001
。
- 安装nginx:
apt update apt install nginx
- 创建配置文件
vim /etc/nginx/conf.d/ssh_agent_8001.conf
ssh_agent_8001.conf
内容如下(http
请求80端口,https
请求443
端口,根据自身情况修改)server { listen 80; server_name _(填写域名,不填的话请删除这个括号内容); location / { proxy_pass http://127.0.0.1:8001; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
- 重启nginx使配置生效
service nginx restart
4. 浏览器访问网站即可
二、基于ssh实现远程访问内网服务器
1. 内网服务器:建立反向代理
-
内网服务器的
22
端口和公网服务器的8022
端口建立ssh连接ssh -fCNR 8022:localhost:22 -o ServerAliveInterval=60 user_gong@100.100.100.100 -p 22 # ssh -fCNR [公网IP(可省略)]:[公网端口]:[本机IP]:[本机端口] [公网用户名@公网IP] -p [公网ssh端口(默认22)] # 或者使用autossh: # autossh -M 8999 -CNR 8022:localhost:22 user_gong@100.100.100.100 -p 22
该命令实现的功能是,让一个远端机器的
8022
端口代理自己的22
端口,这里所说的远端机器就是我们的公网服务器。 -
执行
ps aux | grep ssh
可查看是否成功启动了该进程。
2. 公网服务器
- 查看是否成功建立了连接
netstat -antpul | grep 8022
-
也可以使用
lsof
查看进程PID,以便kill进程。lsof -i:8022
-
至此,我们就可以在公网服务器上直接访问内网内网了!
- 从公网服务器的终端上直接登录到内网服务器:
ssh user_nei@localhost -p 8022
- 从公网服务器的终端上向内网服务器
/home/
下发送文件:scp -P 8022 filename user_nei@localhost:/home/
3. 公网服务器:正向代理
前面实现的反向代理端口8022
,但这个端口只允许公网服务器内部访问。也就是说,只能先用ssh登录公网服务器,然后在终端上使用ssh访问8022
端口才能真正登录到内网服务器。那能不能直接从个人电脑上登录到内网服务器呢?能~
-
公网服务器:让
8023
代理8022
(*
表示接受来自任意机器的访问)ssh -fCNL *:8023:localhost:8022 -o ServerAliveInterval=60 user_gong@localhost -p 22 # ssh -fCNL [本机IP(可省略)]:[本机端口]:[远端IP]:[远端端口] [远端用户名@远端IP] -p [远端ssh端口(默认22)] # 或者使用autossh: # autossh -M 8999 -CNL *:8023:localhost:8022 user_gong@localhost -p 22
该命令实现的功能是,让本机
8023
端口指向一个远端机器的8022
端口,而这里的远端机器恰好就是公网服务器本身。 -
执行
ps aux | grep ssh
可查看是否成功开启了进程。
4. 个人电脑使用ssh远程登录内网服务
ssh user_nei@100.100.100.100 -p 8023
# ssh [内网服务器用户名]@[公网服务器IP] -p [代理端口]
- 可能遇到的问题
请前往内网服务器执行apt install openssh-server service ssh restart
参考资料
https://www.cnblogs.com/kwongtai/p/6903420.html
https://segmentfault.com/a/1190000002718360