FRP进行NAT穿透实践

什么是NAT穿透

NAT穿透涉及TCP/IP网络中的一个常见问题,即在处于使用了NAT设备的私有TCP/IP网络中的主机之间创建连接的问题。大多数NAT穿透技术都要求有一台拥有公网IP的公共服务器,通过这个公共服务器进行数据中继,这也会引入带宽开销的问题。

简单的说NAT穿透就是实现不同局域网内的主机之间通过互联网进行通信的技术。

NAT网络地址转换

NAT(Network Address Translation,又称网络地址转换)是一种在IP数据包通过路由器或防火墙时重写来源IP地址或目的IP地址的技术。这种技术被普遍使用在有多台主机但只通过一个公有IP地址访问互联网的私有网络中。NAT通常部署在一个组织的网络出口位置,通过将内部网络IP地址替换为出口的IP地址提供公网可达性和上层协议的连接能力。

早期,NAT作为一种解决IPv4地址短缺的方案而流行被广泛使用,后续NAT就成了家庭和小型办公室网络连接上的路由器的一个标准特征。

一般来说一个本地网络使用一个专有网络的指定子网(比如192.168.x.x或10.x.x.x)和连在这个网络上的一个路由器。这个路由器占有这个网络地址空间的一个专有地址(比如192.168.0.1),同时它还通过一个或多个因特网服务提供商提供的公有的IP地址(过载NAT)连接到因特网上。当信息由本地网络向因特网传递时,源地址从专有地址转换为公用地址。由路由器跟踪每个连接上的基本数据,主要是目的地址和端口。当有回复返回路由器时,它通过输出阶段记录的连接跟踪数据来决定该转发给内部网的哪个主机;

104127213-c8de9a00-539b-11eb-82b0-c0759af77705

基本NAT和端口号转换

  • 基本网络地址转换(Basic NAT):

也称静态NAT,仅支持地址转换,不支持端口映射。维护一个公网的地址池,将内部网络的私有IP地址转换为公有IP地址,IP地址对是一一对应的。由于改变了IP源地址,在重新封装数据包时候必须重新计算校验和,网络层以上的只要涉及到IP地址的头部校验和都要重新计算。

Basic NAT要维护一个无端口号NAT表。

图片

  • 网络地址端口转换(NAPT):

支持端口的映射,采用端口多路复用的方式,并允许多台主机共享一个公网IP地址。分两种类型:源地址转换与目的地址转换。

  • 源地址转换发起连接的计算机的IP地址将会被重写,使得内网主机发出的数据包能够到达外网主机。
  • 目的地址转换被连接计算机的IP地址将被重写,使得外网主机发出的数据包能够到达内网主机。

一般会一起使用以支持双向通信。NAPT维护一个带有IP以及端口号的NAT表。

图片

DDNS

DDNS(Dynamic DNS,动态DNS,动态域名服务)是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器程序负责提供DNS服务并实现动态域名解析。

DDNS捕获用户每次变化的IP地址,然后将其与域名相对应,这样其他上网用户就可以通过域名来进行交流。

NAT穿透的障碍

  1. 位于局域网内的主机有两个IP 地址,一个是内部网络私有 IP,一个是经过NAT转换后的外网 IP 地址,用于与外网程序进行通信。
  2. 局域网内除非主机主动向外部发送连接请求,当路由设备接收到外部数据包时,如果查询不到对应的记录,这些数据包将会被丢弃。

NAT穿透的常见方案

基于frp的NAT穿透原理

frp分为服务端frps与客户端frpc,frps运行在拥有公网IP的服务器上,frpc运行在局域网内的设备上,服务端默认会先开放 7000 端口,然后与客户端相连,进行网络桥接。

同时frpc可以开启某个端口与服务端的某个端口做映射,如22(ssh)、5901(vnc)、3389(rdp);这样我们访问frps部署的服务端的端口时,会自动转发到安装了frpc客户端去。

图片

FRP实践

服务器部署frps

  1. 下载frp程序
wget https://github.com/fatedier/frp/releases/download/v0.34.3/frp_0.34.3_linux_amd64.tar.gz
tar -zxvf frp_0.34.3_linux_amd64.tar.gz
  1. 程序相关文件
frpc          # frp client
frpc_full.ini # 完整frp client 配置文件
frpc.ini      # frp client 配置文件
frps          # frp server
frps_full.ini # 完整frp server 配置文件
frps.ini      # frp server 配置文件
  1. 配置frps.ini

基本配置如下所示,具体详细配置参考官方文档

bind_port = 80077 					# frps监听端口
kcp_bind_port = 80077				# frps kcp监听端口
dashboard_port = 80075				# dashboard 监听端口
token = ** 							# 鉴权使用的 token 值,和frpc配置一致
dashboard_user = admin				# dashboard用户名
dashboard_pwd = ***					# dashboard密码
  1. 启动frps

这里使用简单的shell脚本进行frps 启动、关闭操作。

#! /bin/bash

FRP_DIR=/home/frp

d_echo(){
  echo [auto-robot] `date +%F\ %T` $1
}

frp_start(){
    d_echo "start up frp server"
    nohup ${FRP_DIR}/frps -c ${FRP_DIR}/frps.ini &
    d_echo "start up frp server done"
}

frp_close(){
    d_echo "close frp server"
    FRP_PID=`ps -ef|grep "${FRP_DIR}/frps"|grep -v grep|awk '{print $2}'`
    if [[ ${FRP_PID} ]]; then
        d_echo "try kill ${FRP_PID}"
        kill -9 "${FRP_PID}"
        d_echo "close frp server successful"
    else
        d_echo "close frp server failure"
    fi
}

frp_restart(){
frp_close
sleep 5
frp_start
}

case $1 in
   start) frp_start
   ;;
   close) frp_close
   ;;
   restart) frp_restart
   ;;
esac

内网设备安装frpc

  1. 下载frpc程序
  2. 配置frpc.ini
[common]
server_addr = 服务器公网地址
server_port = 80077
token = **

# 配置rdp端口映射,本地3389映射到服务器的3389
[rdp]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 3389
  1. 启动frpc程序
frpc -c frpc.ini

参考

https://gofrp.org/docs/