自建一个服务器,如何使外网设备访问到内网服务器,将是个麻烦问题。下面我将介绍一些可以解决这一问题的常用办法,也就是内网穿透或者说端口映射。

将这些方法分为三大类:

第一类适用于没有公网ip或具有公网ip的服务器的情形(家庭拨号网、校内或公司局域网)

第二类适用于有公网ip的客户端的情形

第三类适用于有具有公网ip的服务器的情形。

 

第一类

我相信大多数人面临的是第一种情形,毕竟公网ip较难获取。

(一)、 nat123的端口映射

nat123对Linux、Windows、Android都适用,在其官网上都有相应的教程:

Linux版教程 / Windows版教程 / Android版教程

nat123提供了比较丰富的端口映射功能,有http映射(80端口)、https映射(443端口)、非80端口、非网站(其他端口)、全端口映射、全映射等。提醒大家注意,除全端口映射外,其他服务是不需要在访问侧(外网)加装p2p访问者软件的,可以方便使用【全映射是全端口映射的面p2p访问者软件版本】。nat123有免费线路,也有收费服务,具体的收费情况大家自己再行了解。

简单说一下全端口映射,以树莓派的vnc服务为例,首先你需要在nat123官网注册一个账号,然后树莓派上安装好nat123软件,并在本地APP上登录账号。nat123的端口映射管理功能在官网上【而不是在本地进行,或者说它只是没有告诉我们如何在本地进行管理】,所以你需要在nat123官网上添加端口映射时选择全端口映射(仅p2p),然后在安卓手机或Windows上安装p2p访问者(nat123官网下载),运行端口映射服务与vnc服务,对vnc来说,端口号=5900+桌面号,例如桌面号为1,那么端口号就是5901,打开p2p访问者,添加访问端口5901,注意p2p访问者要在后台运行,不要关掉,然后打开vnc viewer,输入域名和端口号5901,即可访问树莓派了。

nat123配置较为简单,容易上手;有开放免费线路且使用体验较好;Linux/Windows/Android皆可使用,可能适合较多的人。

(二)、 花生壳内网穿透

说到内网穿透,网上很多人都会提到花生壳的内网穿透。很多年前我使用花生壳的时候,这个服务确实还是可以的,免费,而且连接速度OK,现在用的人太多,速度自然降下来了,也开始提供付费服务了。大家浏览花生壳官网即可,我点到为止。

花生壳官网:https://www.oray.com

(三)、 Holer

Holer的GitHub地址:https://github.com/Wisdom-Projects/holer

Holer是基于SSH的内网穿透服务。在Holer仓库的readme文档下有使用指南,没什么技术难度,我就简单说说:例如你想远程SSH登陆你的树莓派,将conf/holer.conf文件中原有的Holer Access Key修改为针对SSH服务的Holer Access Key,再启动Holer即可,服务端就配置完成了。Holer提供的SSH服务的映射端口是holer.org:65534,则在客户端的连接方式是:

ssh pi@holer.org -p 65534

可以看到,Holer的配置确实简单,但是其问题也十分明显,只有一个Holer Access Key作为唯一标识,大家都是用这个Key,下一个人使用了,上一个人就被踢下来了,所以体验相当糟糕。想使用Holer的人就要注意了。

Holer也提供了独立的Access Key,这是需要付费开通的。在我文章评论区打广告的Holer营销人员,还想说“配置比较简单”的,请免开尊口,配置简单别的就不考虑了吗?不要影响朋友们选择!

 

第二类

由于公网IPv4地址资源稀有,目前家庭网络中服务提供商分配的名义上的公网ip实际上都是NAT后的内网ip【ISP的内网】,表现为在网关中查到的公网ip与用查ip网站查到的公网ip不一致。此时你可以致电服务提供商咨询是否可以帮你改为真的公网ip(以“安装监控”为由)。

如果可以获得公网ip,单台服务器的情况下,你可以直接将网线插到服务器上;而如果有多台服务器都需要使用公网ip的话,下面的方法可以帮到你:

(一)、 路由器的虚拟服务器(端口映射)功能

这种方法需要一个带有端口映射功能的路由器。我以中兴的天翼网关和树莓派motion网络服务为例。配置时,其中外部端口是外网访问的端口,例如可选9000,建议不要太小,因为服务提供商可能屏蔽较小的一些端口;内网端口是motion的端口,为8081或8080;协议选TCP;内部IP是树莓派的局域网ip。例如你的公网ip为59.60.84.xxx,这些设置完以后就可以在浏览器中输入59.60.84.xxx:9000,即可看到实时画面。

 

如果没有具有端口映射功能的路由器,那么将网线插入一台电脑做网关也是可行的,但你还需要解决的是各服务器之间网络连接的问题,如何使其他服务器连上这台电脑,是通过网线桥接还是无线连接(可能不大稳定)需要自行衡量。我各推荐一款Windows和Linux上的端口映射工具:

(二)、 Windows上专用的端口映射工具PortTunnel

PortTunnel是一个实现端口映射的专用工具。它是一个直接运行的软件。如果操作系统为Windows NT/Windows 2000/Windows XP,第一次运行时选择Start,PortTunnel会自动以服务方式运行。点击[Add]按钮添加条目,点击[Edit]按钮编辑现有条目,点击[Delete]按钮删除条目。

在这个“新建/编辑端口映射”对话框中,我们要给该条目命名,然后设定输入端口(Port In)、绑定地址(Bind address)、输出端口(Port Out)和输出地址(Address Out)。其中,“绑定地址”是指监听该主机的哪一个IP(内部IP还是外部IP)。设为“Any(0.0.0.0)”则监听该主机的全部IP。

PortTunnel专门针对HTTP、FTP、SMTP服务的端口映射,提供了较多的参数设置,在相应的标签菜单下调整。此外,PortTunnel还提供了安全性设置和日志、统计等功能。

附一篇教程:《PortTunnel [端口映射软件] 使用配置说明》

(三)、 Linux端口映射工具:RINETD

RINETD可以算得上Linux上最为简单好用的端口映射工具了,安装配置均很简单。在此我也就不展开说了,附一篇教程:《rinetd 一个linux下的端口转发工具》,若有需要,学着这个教程做一下就行。

 

第三类

如果你有一个有公网ip的服务器,那做起内网穿透会有很大的自由度。

(一)、 ssh内网穿透

我将ssh内网穿透放在第一位,因为它只经过自己的服务器,按照自己设定的命令进行操作,所以比较安全、稳定。

 

理论部分

ssh的三个强大的端口转发命令:

转发到远端:ssh -C -f -N -g -L 本地端口:目标IP:目标端口 用户名@目标IP

转发到本地:ssh -C -f -N -g –R 本地端口:目标IP:目标端口 用户名@目标IP

动态端口转发:ssh -C -f -N -g -D listen_port 用户名@目标IP

-C:压缩数据传输。

-f :后台认证用户/密码,通常和-N连用,不用登录到远程主机。

-N :不执行脚本或命令,通常与-f连用。

-g :在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。

-L 本地端口:目标IP:目标端口:将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-R 本地端口:目标IP:目标端口:将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有用 root 登录远程主机才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-p :被登录的ssd服务器的sshd服务端口。

-D listen_port:指定一个本地机器 “动态的'’ 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4 协议, 将充当 SOCKS4 服务器. 只有 root 才能转发特权端口. 可以在配置文件中指定动态端口的转发.

 

实践部分

(1)只有树莓派和服务器

步骤①在树莓派上,通过远程端口映射,将服务器的2222端口映射到树莓派的22端口:

ssh -fNR 2222:localhost:22 root@公网IP

步骤②服务器上访问树莓派:

ssh -p 2222 pi@localhost

但事实上,有时候我们可能更需要另一个设备可以访问树莓派,而不是在服务器上访问。因此这个时候我们就需要做两次映射。

(2)树莓派、服务器、第三方设备

步骤①在树莓派上,通过远程端口映射,将服务器的2222端口映射到树莓派的22端口:

ssh -fNR 2222:localhost:22 root@公网IP

步骤②在第三方设备上,通过本地端口映射,将第三方设备的2222端口映射到服务器的2222端口:

ssh -fNL 2222:localhost:2222 root@公网IP

步骤③在第三方设备上访问树莓派:

ssh -p 2222 pi@localhost

 

除了ssh内网穿透外,我们还可以借助许多的反向代理工具来实现内网穿透,常见的有frp、ngrok、n2n等。

(二)、 frp内网穿透

GitHub仓库:https://github.com/fatedier/frp

GitHubReleases:https://github.com/fatedier/frp/releases/

根据服务器/客户端所属架构与系统,在releases中分别下载合适的版本,并解压出来。

frps.ini是服务器端的配置文件,配置如下:

[common]
bind_port = 6666

记住bind_port是frp服务的监听端口。

启动服务端frps:

./frps -c ./frps.ini

而在客户端,我们要修改的配置文件是frpc.ini(以ssh服务为例):

[common]
server_addr = x.x.x.x
server_port = 6666
 
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 2222

server_addr是服务器的公网ip,server_port是服务器上设置的frp服务的监听端口。

[ssh]部分的local_port是ssh服务的本地端口,默认是22,而remote端口并不是6666,而是由自己另外指定的服务器上ssh转发的目标端口,这里我选择2222。

启动客户端frpc:

./frpc -c ./frpc.ini

正确连接后,访问本地服务器则可以使用以下命令:

ssh pi@公网ip -p 2222

 

(三)、 ngrok内网穿透

请看《自搭Ngrok实现树莓派内网穿透》

(四)、 n2n内网穿透:

请看《n2n内网穿透神器(一条命令实现穿透)(linux,安卓,win,openwrt全介绍)》

 

参考文献/推荐教程

 nat123:Linux版教程 / Windows版教程 / Android版教程

《PortTunnel [端口映射软件] 使用配置说明》

《rinetd 一个linux下的端口转发工具》

《实战SSH端口转发》

《frp内网穿透》

《自搭Ngrok实现树莓派内网穿透》

《n2n内网穿透神器(一条命令实现穿透)(linux,安卓,win,openwrt全介绍)》

 

 

参考推荐

花生壳动态域名解析 DDNS 原理

内网和外网之间的穿透通信:端口映射原理

通过外网访问内网服务器(绝对成功)