上面是一张NAT的图,通常情况下:
- 一个请求从内网IP发出到一个公网IP
- 这时由于目的地是公网IP,很自然就能通过路由找到目的地,然后建立双向连接,这时内网IP上的服务可以和公网IP上的服务进行通信
- 注意,这时是内网IP主动向公网IP发起请求
那么如果从一个公网IP能向内网IP发起请求吗?
- 不可以,因为内网IP会解析到人家的内网,而不是我们的内网
- 既然无法通过内网IP唯一确定一台机器那么内网IP向公网IP发起请求时,公网IP怎么知道怎么给内网IP响应数据的,实际上这是一跳一跳返回的,直到内网的网关处,所以就是内网向公网发起请求,内网通过NAT再网关处有一个临时的公网地址,响应到网关后自然知道内网ip在什么地方
- 所以很简单,如果固定这个映射,就可以达成一个稳定内网穿透效果
内网穿透就是通过 NAT设备(或软件)去维护一个状态表,用来把内部网络的私有IP地址映射到外部网络的合法IP地址上去,从而达到内外通信的目的。
固定的内网穿透由两种手段
- 使用硬件
- 使用软件,需要一个完全可控的公网ip
IPv4使用32位(4字节)地址,因此地址空间中只有4,294,967,296(2的32次方)个地址。
有很多程序扫描公网IP的端口尝试爆破。
frp
Fast Reverse Proxy (FRP)
frp 由客户端(frpc)和服务端(frps)组成,服务端部署在有公网 IP 的机器上,客户端部署在需要穿透的内网服务的机器上。用户可以通过访问frps服务端,然后由frp根据请求将数据包路由到对应的内网服务器,从而实现内外网之间的通信需求。
在 frp 中一个代理对应一个需要暴露的内网服务。一个客户端支持同时配置多个代理。
https://github.com/fatedier/frp/releases
wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz
tar -zxvf frp_0.61.1_linux_amd64.tar.gz
两台机器,内网机器A,公网机器B
内网机器web服务
# 假定为一个简单文件服务
python -m http.server --bind 127.0.0.1 --directory /tmp/ 8000
首先需要在公网机器B启动一个frp服务端
frps.toml
bindPort = 7000 # frp监听7000来响应frp客户端请求
vhostHTTPPort = 8080 # frp服务端监听 8080 端口作为http服务端口
启动frp服务端
./frps -c frps.toml
在内网机器A启动一个frp客户端
frpc.toml
serverAddr = "137.175.109.104" # frp服务端 ip
serverPort = 7000 # frp服务端 端口
[[proxies]]
name = "test-http"
type = "http"
localPort = 8000 # 内网机器A的http端口
customDomains = ['137.175.109.104'] # 指定域名,frp服务端会将来自该域名的请求转发到本代理,直接设置为服务器ip就相当于全部转发
启动客户端
./frpc -c frpc.toml
以上成功代理
访问137.175.109.104:8080即可访问内网机器web服务
ssh也是一种非常轻量的方式
https://blog.huohaodong.com/blog/using-ssh-tunnel-to-access-cloud-server-intranet-services