住的地方有个台式机,刷了个 RedHat,上面跑着各种服务。但办的宽带并没有公网 IP,而有些服务需要暴露到互联网上。所以需要一些内网穿透的工具,实现在外部访问内部服务。本文将介绍两种方式:
- 使用 ssh 远程端口转发
- 使用 cloudflare zertorust 的端口映射
其中使用ssh的方式需要一些linux的使用知识,需要花钱去购买云服务器,好处在于更加灵活,买来的linux服务器可以做其它事情。使用cloudflare话,则需要一个域名。
1. 使用 ssh 远程端口转发
ssh(s
ecurity sh
ell) 一般用做本地和远程服务器之间的连接。然而它更加重要的功能是端口转发。
所谓远程端口转发(remote port forward),就是把本地某个端口(c
)映射到远程某个端口(d
)上。想象你在笔记本上开发了一个网站,你希望外出的时候也能给你朋友展示一下你的牛逼大作。显然你无法每次都把笔记本带在身边,但是你会随身携带手机。所以用手机随时随地地访问这个网站就是一个不错的方案。那你就需要remote forward了,就是把你本地的一个端口映射到远程的某个服务器上。你通过访问远程服务器某个端口实现对你笔记本上某个服务进行访问。
显然你需要一个远程服务器,你能够通过手机随时随地访问到你这个服务器。使用这种方式需要购买一个带有公网 ip 的云服务器。
1.1 远程服务器购买c
这里推荐使用 vultr 的 vps,它按使用量收费,而且支持支付宝付款。
1.2 远程服务器 ssh 安装和配置
通常购买的云服务器会开启 sshd 服务,否则就无法通过 ssh 连接。关于云服务器的配置,可以查看这里。但是也可能遇到奇葩的云服务器,需要先安装 ssh,这里用openssh:
sudo dnf install openssh-server -y
安装完成之后,需要在远程服务器上开启 sshd 服务:
sudo systemctl enable sshd.service
sudo systemctl start sshd.service
同时要在防火墙中开启 ssh 的22
端口:
sudo firewall-cmd --add-port 22/tcp --zone=public --permanent
sudo firewall-cmd --reload
有的云服务器还有自己的防火墙,要登陆网页去修改防火墙,放行一些端口:
- 22端口,一般是开放的
- 远程端口
d
,你在外面想要通过远程端口d
来访问你的内网服务。
至此,你已经可以通过ssh的方式来访问你的服务器了。
但是为了实现端口转发,还要配置服务器上的 sshd 服务,使其允许端口转发,修改/etc/ssh/sshd_config
:
AllowAgentForwarding yes
AllowTcpForwarding yes
GatewayPorts yes
在远程服务器上重启 sshd 服务:
sudo systemctl daemon-reload
sudo systemctl restart sshd.service
至此,服务器端的配置已经完成了。
1.3 客户端用 ssh 连接
在本地服务器上连接远程云服务器:
ssh -N -R remote_port:localhost:local_port user_name@server_ip
-N
让 ssh 不要登陆远程服务器-R
远程端口转发,R 是 remote 的意思,通过访问远程服务器的remote_port
,可以实现访问本地服务器local_port
的效果
如果是第一次连接,会问你是否要将远程服务器的地址加入known_hosts
里,在输入命令之后,问你是否加入,敲一下回车就行。
1.3.1 SSH 密钥(免密码)登陆
当然,一般要免密码登陆,需要配置 sshkey。在本地服务器上运行:
ssh-keygen -t rsa # 然后就回车几次
默认会在~/.ssh/
文件夹下生成id_rsa.pub
文件,将这个文件从本地服务器传送到远程云服务器。在本地服务器上运行:
scp ~/.ssh/id_rsa.pub user_name@server_ip
在远程服务器上处理公钥:
mkdir -p ~/.ssh
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
此时再到本地服务器上运行 ssh 命令:
ssh -N -R remote_port:localhost:local_port user_name@server_ip
可以发现不需要输入密码就能登陆了。通常我会将本地的 22
端口远程转发到云服务器的另外一个端口(比如2022
)。然后公网访问:
ssh -p 2022 client_user@server_ip
1.4 autossh 自动连接 systemd 管理服务
上面直接用 ssh 的方式已经能够实现远程端口转发了。但是问题是每次都要运行一下 ssh 命令,也没有办法开机启动。这时候可以用 autossh 和 systemd 来进行操作。
1.4.1 autossh 自动连接 ssh
首先在本地服务器上安装 autossh:
sudo dnf install autossh -y
将之前的 ssh 命令更换:
autossh -M manage_port -i ~/.ssh/id_rsa -N -R remote_port:localhost:local_port user_name@server_ip
这样在 ssh 掉线的时候自动重新连接了。
1.4.2 systemd 管理服务
经过上面的操作,还是没有做到开机自动启动,此时需要在本地服务器上用 systemd 来管理服务。
新建/etc/systemd/system/auto_ssh_server.service
:
[Unit]
Description=Auto SSH Server Servie
StartLimitInterval=180
StartLimitBurst=4
After=network.target
Wants=network.target
[Service]
User=chinglin
Group=chinglin
Type=simple
PIDFile=/run/auto_ssh_server.pid
ExecStart=/usr/bin/autossh -M 4011 -i ~/.ssh/id_rsa -NR remote_port:localhost:local_port user_name@server_ip
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target
# the manage port should be different from the remote listen port
编辑保存后,重启服务:
sudo systemctl daemon-reload
sudo systemctl enable auto_ssh_server.service
sudo systemctl start auto_ssh_server.service
此时本地服务器开机启动这个 autossh 的连接了。我通常会用将本地服务器的 22 端口转发到远程的某个端口(如 2022),这样就可以远程 ssh 到本地了。找到另外一台电脑运行 ssh:
ssh -p 2022 local_server_user@remote_server_ip
2. 使用 cloudflare 进行内网穿透
cloudflare 是一家全球的 CDN 厂商,在中国大陆境内也有相关服务。cloudflare 提供的 zerotrust 套餐,则是很好的内网穿透工具,稳定且免费。
2.1 注册 cloudflare 账户
需要一张 visa 或者 mastercard 的信用卡帮我们注册注册。
2.2 购买一个域名
使用 cloudflare 的 zerotrust 需要一个域名,可以在 cloudflare 或者 namecheap 上购买。
比如在 cloudflare 上购买域名:
2.3 用 cloudflare 解析域名
在购买域名的地方,将域名服务器修改为 cloudflare 提供的域名服务器。这时候要选择一个套餐,选择 0 元套餐就可以了。cloudflare免费套餐真是功德无量。
2.4 cloudflare 的 zerotrust 做内网穿透
1 控制台上找到 zerotrust
2 找到 Access -> Tunnels -> Create a tunnel
3 输入名字相关信息
4 找到名字,选择 configure
5 在本地服务器安装 cloudflare 客户端
这里有多种方式,选择 docker 来安装。拷贝网页上的命令就行了。
6 在 Public Hostname 处添加新的穿透
7 填写相关参数
- subdomain: 想要访问的二级域名
- domain:通过下拉菜单来选择
- path:留空
- service:选择协议,根据实际需要进行选择
- url:填写本地服务器上服务器的 ip 和端口,比如说本地服务器 ip 为 10.10.10.11,端口为 9090,则 url 填写 10.10.10.11:9090。应为 cloudflared 在 docker 中运行,一定要填写服务器 ip(不能是 localhost)
至此,zerotrust 已经配置完成。
2.5 实例,转发 cockpit 到云服务
尝试转发22
端口,发现并不能通过。但是 redhat 有一个插件叫做 Cockpit。可以远程管理我们的机器。在本地机器上安装 cockpit:
sudo dnf install cockpit -y
sudo systemctl enable cockpit
sudo systemctl start cockpit
cockpit 通常使用的是9090
端口,要用 zerotrust 转发9090
端口。
用户名和密码就是本地服务器的账户和密码。
总结
本文介绍了两种内网穿透的方式。一种是用 ssh 的端口转发,另一种是用 cloudflare 的 zerotrust 工具。两种方式均实现了在没有公网 ip 的情况下,将本地服务暴露到整个互联网的功能。