前言
在上一篇文章中, 我介绍了如何通过docker搭建redmine项目管理平台, 然而此时 redmine仅仅只能在内网上才能访问到, 接下来这篇就介绍下如何通过内网穿透和端口转发来让我们随心所欲的访问到.
设备
机器代号 | 机器描述 | 账户 | 地址 | ssh/sshd 端口 |
---|---|---|---|---|
Server | 公网服务器 | server | server.site | 29245 |
Base | 个人电脑(位于NAT之后) | userb | 127.0.0.1 | 22 |
Slave | 垫显示器的MacMini(位于NAT之后) | users | 127.0.01 | 22 |
实现
实现内网穿透及端口转发有很多手段途径, 下面我只介绍两种较简单和常用的.
一种是 基于 SSH 的
另一种是 基于 Frp 的
基于SSH的内网穿透及端口转发
SSH反向隧道
这种手段实质上是由Slave向Server主动建立一个SSH通道, 将Server的某一个端口转发到Slave的SSH端口(22)上.
我们以Server的54345端口为例进行转发:
ssh -fN -R 54345:localhost:22 server@server.site -p 29245
# -f Requests ssh to go to background just before command execution.
让该命令后台运行 .
# -n Redirects stdin from /dev/null (actually, prevents reading from stdin).
# -N Do not execute a remote command.
不执行远程命令 .
# -R 远程转发
上面, 我们将Server的54345端口转发到了Slave的22端口上, 只要这个隧道不关闭, 我们就可以在Base上通过访问A的54345端口来连接Slave的22端口上.
# 在Base机器上
ssh slave@server.site -p 54345
隧道的维持
由于SSH存在超时关闭的可能, 而一旦链接关闭, 隧道便无法维持, 那么Base也就无法随心所欲的访问Slave了, 为此我们需要一种方案来提供一条稳定的SSH 反向隧道.
一个最简单的方法就是autossh,这个软件会在超时之后自动重新建立SSH 隧道.
- 安装SSH
# MacMini- MacOS
brew install autossh
- 配置autossh
autossh -M 5678 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval 60" -o "Serv erAliveCountMax 3" -R 54345:127.0.0.1:22 server@server.site -p 29245
# “-M 5678” 选项指定中继服务器上的监视端口,用于交换监视 SSH 会话的测试数据。中继服务器上的其它程序不能使用这个端口。
# “-o XXXX” 选项让 ssh:
# * 使用密钥验证,而不是密码验证。
# * 自动接受(未知)SSH 主机密钥。
# * 每 60 秒交换 keep-alive 消息。
# * 没有收到任何响应时最多发送 3 条 keep-alive 消息。
```
如此, 便可保证在不重启Slave的情况下的稳定SSH链接.
### 端口转发到docker的服务
[在上一篇文章中](http://blog.onekyle.com/2018/07/14/%E5%9F%BA%E4%BA%8Edocker%E6%90%AD%E5%BB%BA%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0redmine/#docker%E5%90%AF%E5%8A%A8redmine)我们在Slave机器上对docker的物理机3000端口与虚拟机的3000端口做的了映射, 所以外部用户可以通过3000端口直接访问docker的redmin服务.
此时, 只需要通过SSH隧道将Slave的3000端口转发到Server的某个端口上, 就可以了.
ssh -fN -R 3000:localhost:3000 server@server.site -p 29245
如此, 我们便可以通过访问server.site:3000端口就可以直接访问到位于Slave的redmine服务.
## 基于Frp的内网穿透及端口转发
<span id = "frp"></span>
[frp](https://github.com/fatedier/frp/blob/master/README_zh.md) 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议.
frp可以利用处于内网或防火墙后的机器,对外网环境提供 http 或 https 服务.
对于 http, https 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个80端口.
也可以利用处于内网或防火墙后的机器,对外网环境提供 tcp 和 udp 服务,例如在家里通过 ssh 访问处于公司内网环境内的主机.
### 安装frp
Server(公网服务器)与Slave(内网服务器)都需要安装frp, 下载地址是[https://github.com/fatedier/frp/releases](https://github.com/fatedier/frp/releases).
Linux
wget https://github.com/fatedier/frp/releases/download/v0.21.0/frp_0.21.0_linux_amd64.tar.gz
MacOS
curl -OL https://github.com/fatedier/frp/releases/download/v0.21.0/frp_0.21.0_darwin_amd64.tar.gz
解压
tar -zxvf frp_0.21.0_linux_amd64.tar.gz
### Server端配置
1. 基本配置
在Server端中下载好frp, 解压完成后就cdj进入, 然后编辑frps.ini文件, 添加如下代码.
[common]
与客户端绑定的进行通信的端口
bind_port = 7000
http的访问端口
vhost_http_port = 80
https的访问端口(如果需要的话)
vhost_https_port = 8080
然后我们只需要运行如下命令就可以了
./frps -c ./frps.ini &!
2. 开机自动运行&自动重连
这里以通过systemd来初始化为例, 我们只需要编写一个service文件就可以(其他情况请参看[https://github.com/fatedier/frp/issues/176](https://github.com/fatedier/frp/issues/176))
// 进入相关文件
cd /etc/systemd/system/
// 创建service文件
touch frps.service
然后将如下代码写入到frps.service中
[Unit]
Description=frps daemon
After=syslog.target network.target
Wants=network.target
[Service]
Type=simple
ExecStart=/home/ubuntu/frp/frps -c /home/ubuntu/frp/frps.ini & #这里地址需要改成自己frp的地址
Restart= always
RestartSec=1min
ExecStop=/usr/bin/killall frps
[Install]
WantedBy=multi-user.target
最后启用并启动服务:
sudo systemctl enable frps
sudo systemctl start frps
// 查看运行状态
sudo systemctl status frps
如果服务的状态是`active`就表示运行成功了.
### 客户端(Slave)配置
1.基本配置
下载解压后进入目录, 编辑`frpc.ini`文件:
[common]
server_addr = server.site # 如: 123.206.87.36
server_port = 7000 # 与Server端中frps.ini文件中设置的一样.
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 20022
[jenkins]
type = tcp
local_ip = 127.0.0.1
local_port = 8080
remote_port = 28080
[redmine]
type = tcp
local_ip = 127.0.0.1
local_port = 3000
remote_port = 23000
2.后台执行
./frpc -c ./frpc.ini &!
```
在frpc.ini
文件中分别配置了三对映射, 这时我们便可以通过访问映射好的ip地址来访问到Base(客户端)的服务.
访问redmine
参考
实战 SSH 端口转发 深入浅出的介绍了SSH端口转发的原理.