端口映射的实验
1、名词介绍
“内网”与“外网”的概念:
内网:即所说的局域网,比如学校的局域网,局域网内每台计算机的IP地址在本局域网内具有互异性,是不可重复的。但两个局域网内的内网IP可以有相同的。
外网:即互联网,局域网通过一台服务器或是一个路由器对外连接的网络,这个IP地址是惟一的。也就是说内网里所有的计算机都是连接到这一个外网IP上,通过这一个外网IP对外进行交换数据的。也就是说,一个局域网里所有电脑的内网IP是互不相同的,但共用一个外网IP。(用ipconfig/all查到的IP是你本机的内网IP;在www.ip138.com上看到的是你连接互联网所使用的IP,即外网)。
在局域网中,每台电脑都可以自己分配自己的IP,这个IP只在局域网中有效。而如果你将电脑连接到互联网,你的网络提供商(ISP)的服务器会为你分配一个IP地址,这个IP地址才是你在外网的IP。两个IP同时存在,一个对内,一个对外。
当有两台电脑,你想组建一个局域网,你除了要用网线和路由器等设备将两台电脑相连,你还要将两台电脑设置固定IP,比如电脑A设为192.168.1.2,电脑B设为192.168.1.3,这样你就可以用这两个IP地址互相访问两台电脑,但这两个IP地址只在这两台电脑间有效,对外网无效。所以局域网中分配的IP与广域网中的IP完全没有对应关系。
你在内网的机子在上网时,都是在向网关发出请求,再由网关(一般为路由器)用外网IP转到INT网上,接受数据后,再分发到你的内网IP上。
公有 IP 和私有 IP 的区别
公有地址(Public address):由 Inter NIC(Internet Network Information Center 因特网信息中心)负责。这些 IP 地址分配给注册并向Inter NIC提出申请的组织机构,公有 IP 全球唯一,通过它直接访问因特网(直接能上网)。
私有地址(Private address):属于非注册地址,专门为组织机构内部使用,说白了,私有 IP 不能直接上网。
而我们平时通过运营商(电信、移动、联通宽带等)上网,家里面通过路由器分出来的 IP 都是私有 IP(局域网 IP),大家可能会疑问,我们可以上网啊,怎么会是私有 IP 呢?租用(申请)公有 IP 是需要钱的。 运营商买了一些公有 IP,然后通过这些公有 IP 分出来,再分给一个一个的用户使用。这个过程有点类似于,我们去安装了宽度,通过路由器分出几个 IP,让好几个人都能上网,当然运营商通过公有 IP 分出来的过程肯定比这个复杂多了。所以,我们平时上网用的 IP 是私有 IP,真正拥有公有 IP 的是运营商(当然,我们可以租用一个公有 IP )。所以,A 家庭的局域网 IP 和 B 家庭的局域网 IP 相同很正常,但是,最终 A 和 B 能上网(数据走出去)还是通过运营商的公有 IP,毕竟,公有 IP 的资源有限,这一片区域的用户使用的很有可能(实际上就是这样的)是同一个公有 IP,这样的话,又回到前面的问题,假如 A 和 B 的局域网 IP 相同(192.168.31.11),当他们同时访问百度服务器的时候,百度服务器如何区分哪个是 A,哪个是 B 呢?
端口映射
端口映射分为动态映射和静态映射。动态端口映射实际上是NAT网关的工作方式。静态端口映射在NAT网关上打开一个固定端口,然后设置端口接收的数据将转发到哪个IP和端口。无论是否成功连接,映射关系始终存在。
动态端口映射是 NAT 的一种,它将外网主机的 IP 地址的一个端口映射到内网中一台机器,提供相应的服务。当用户访问该 IP 的这个端口时,服务器自动将请求映射到对应局域网内部的机器上。
让虚拟机的端口映射到公网,通过公网直接可以访问虚拟机
2、通过路由器映射
虚拟机使用桥接,改成自动分配的,或者手工指定一个与你本机在同一网段的IP地址,然后在路由上面把端口映射指向你的虚拟机的IP地址即可!
3、Ngrok实现端口映射
以centos系统为例:
-
下载安装包
linux:https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
-
解压
$unzip /path/to/ngrok.zip
-
连接账户
运行此命令会将帐户的authtoken添加到ngrok.yml文件中。所有开放式隧道都将列在仪表板中。
$ ./ngrok authtoken 1OoqLBzQetcHL1z5gPIB6drZlfz_3WybfFtGXEL8CJ3vTRkuK
-
运行ngrok
我这边主要是实现ssh远程的功能,所以映射22端口就行
$ ./ngrok tcp 22
要在端口80上启动HTTP隧道,请运行以下命令:
$ ./ngrok http 80
帮助信息:
$ ./ngrok help
国内版的操作:
-
注册账号
-
点击开通隧道——点击免费服务器
-
选择tcp隧道名称随便写选择远程端口——点击确认开通
-
点击隧道管理可以看到添加的隧道信息——点击客户端下载下载对应的客户端
安装教程linux:http://www.ngrok.cc/_book/start/ngrok_linux.html
安装教程windows:http://www.ngrok.cc/_book/start/frp_windows.html
4、frp内网穿透实现ssh访问内网主机
frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透。
架构
frp实际使用时,会按照端口号进行对应的转发,原理如下图所示。
配置 ssh 访问内网机器
根据不同的系统架构选择不同的安装包,从 frp下载链接 上下载合适的安装包。由于本人的公网服务器是 vultr 上面的一台 VPS,操作系统是 CentOS 7;内网机器也是一台 Linux 服务器,操作系统是 Ubuntu 16.04,所以我使用的安装包是 frp_0.21.0_linux_amd64.tar.gz 。配置步骤如下:
下载安装包
下载:https://github.com/fatedier/frp/releases
教程:frp中文文档
https://github.com/fatedier/frp/blob/master/README_zh.md
示例:frps.ini服务端,全配置参数
https://github.com/fatedier/frp/blob/master/conf/frps_full.ini
示例:frpc.ini客户端,全配置参数
https://github.com/fatedier/frp/blob/master/conf/frpc_full.ini
在公网服务器和内网机器上都要下载安装包并解压:
# wget https://github.com/fatedier/frp/releases/download/v0.21.0/frp_0.21.0_linux_amd64.tar.gz
# tar -xzvf frp_0.21.0_linux_amd64.tar.gz
# mv frp_0.21.0_linux_amd64 frp
用到的只有一下4个文件:
将 frps 及 frps.ini 放到具有公网 IP 的机器上。
将 frpc 及 frpc.ini 放到处于内网环境的机器上。
服务端公网ip操作
# cd frp
修改配置文件 # vi frps.ini,如下:
[common]
bind_port = 7000 #frp服务端端口(必须)
配置很简单,然后启动:
# nohup ./frps -c frps.ini &
添加开机自启动:
#printf "nohup /root/frp/frps -c /root/frp/frps.ini &" >> /etc/rc.local
查看 nohup.out 的信息
# tail -f nohup.out
2018/09/14 05:33:15 [I] [service.go:130] frps tcp listen on 0.0.0.0:7000
2018/09/14 05:33:15 [I] [root.go:207] Start frps success
2018/09/14 05:49:47 [I] [service.go:130] frps tcp listen on 0.0.0.0:7000
2018/09/14 05:49:47 [I] [root.go:207] Start frps success
2018/09/14 06:28:59 [I] [service.go:319] client login info: ip [125.71.219.33:37092] version [0.21.0] hostname [] os [linux] arch [amd64]
2018/09/14 06:28:59 [I] [proxy.go:217] [93eec0dde173fc68] [ssh] tcp proxy listen port [6000]
2018/09/14 06:28:59 [I] [control.go:335] [93eec0dde173fc68] new proxy [ssh] success
客户端内网ip操作
修改配置文件# vi frpc.ini,如下:
[common]
server_addr = 0.0.0.0 #frp服务端地址,可以填ip或者域名,这里假设为0.0.0.0
server_port = 7000 #frp服务端端口,即填写服务端配置中的 bind_port
[ssh] #如果有多个内网机器需要修改,例[ssh1]
type = tcp #连接类型,填tcp或udp
local_ip = 127.0.0.1 #填127.0.0.1或内网ip都可以
local_port = 22 #需要转发到的端口,ssh端口是22
remote_port = 6000 #frp服务端的远程监听端口,即你访问服务端的remote_port就相当于访
#客户端的 local_port,如果填0则会随机分配一个端口
启动客户端程序:
# nohup ./frpc -c frpc.ini &
查看 nohup.out 的信息
# tail -f nohup.out
2018/09/14 14:28:58 [I] [proxy_manager.go:300] proxy removed: []
2018/09/14 14:28:58 [I] [proxy_manager.go:310] proxy added: [ssh]
2018/09/14 14:28:58 [I] [proxy_manager.go:333] visitor removed: []
2018/09/14 14:28:58 [I] [proxy_manager.go:342] visitor added: []
2018/09/14 14:28:59 [I] [control.go:246] [93eec0dde173fc68] login to server success, get run id [93eec0dde173fc68], server udp port [0]
2018/09/14 14:29:00 [I] [control.go:169] [93eec0dde173fc68] [ssh] start proxy success
外网登录
完成前面三步的配置就可以登录对应的内网机器了,执行 ssh 命令:
ssh -p 6000 username@server_addr
上面登录使用的 username 是内网机器的用户名,server_addr是公网服务器的IP,port 6000就是设置的 remote_port,最后的登录密码是内网机器的密码,而不是公网机器的密码,这一点一定要注意。
问题项目
在启动服务端和客户端程序之后,可能发现还是无法登录到内网内网机器,在内网机器上面执行 tail -f nohup.out 查看启动命令的执行结果,可以发现以下的问题:
# tail -f nohup.out
2018/09/14 14:11:02 [I] [proxy_manager.go:333] visitor removed: []
2018/09/14 14:11:02 [I] [proxy_manager.go:342] visitor added: []
2018/09/14 14:13:09 [W] [control.go:113] login to server failed: dial tcp xxx.xxx.xxx.xxx:7000: connect: connection timed out
dial tcp xxx.xxx.xxx.xxx:7000: connect: connection timed out
仔细检查了一下,发现是我公网服务器防火墙的原因,没有允许对应端口的流量通过,所以需要配置防火墙:
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 6000:6500 -j ACCEPT #如果是需要添加多个客户端,推荐这样操作
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 7000 -j ACCEPT
添加开机启动
在/etc/rc.local里面添加/root/frp/frps -c /root/frp/frps.ini (文件的具体路径根据实际情况填写),终端里面输入下面的命令,或者把文件下载回本地修改后重新上传覆盖源文件。
vi /etc/rc.local
systemctl来控制启动,客户端
vi /lib/systemd/system/frps.service
在frps.service里写入以下内容
[Unit]
Description=fraps service
After=network.target network-online.target syslog.target
Wants=network.target network-online.target
[Service]
Type=simple
#启动服务的命令(此处写你的frpc的实际安装目录)
ExecStart=/root/frp/frpc -c /root/frp/frpc.ini
[Install]
WantedBy=multi-user.target
然后启动 frps
systemctl start frps
再打开自启动
systemctl enable frps
重启 systemctl restart frps
停止 systemctl stop frps
查看应用日志 systemctl status frps