Linux|【经验】使用FRP搭建内网穿透服务


目录

  • 引入
    • 背景
    • 失败的尝试
    • 新的方案
  • 步骤
    • VPS端
    • 内网server端
    • 测试连通性
    • 尾言

引入 背景 两台 server 没有公网 ip ( server 连接的路由器倒是有教育网的 ip ),boss 想在公网访问,想利用手上一台 vps 做内网穿透,比如把 server 的 1:10000 端口映射到 vps 的 10001:20000 上。vps和server的系统均为ubuntu。
失败的尝试 尝试的做法是 vps 上搭个 o server,两台 server 连接之后用 iptables 的 DNAT 映射把 vps 指定端口转发给 10.8.0.x,但是遇到了两个问题:
  1. iptables 没法非对称映射端口段
    (要么 8000→20000 单个端口映射
    要么 1000:2000→1000:2000 对称映射
    没法 1:10000→10001:20000 非对称的端口段映射)
  2. server 连接 o 之后,server 的全部流量都走那个 o 的虚拟网卡了…
    又因为从 vps 传到 server 的请求是从公网来的,源 ip 都是公网 ip,没法单独区分返回的数据包只让它走虚拟网卡…
    如果o配置上 no-route,那么除了来自虚拟子网、源 ip 是 10.8.0.x 的请求能通过虚拟网卡回去,
    一般来自公网的请求都会尝试走物理网卡回去,也就是实际上收不到返回值…
新的方案 经过v友们的推荐,尝试使用FRP解决:
  1. vps使用frps,使用systemd实现自启动;
  2. 使用某一台server运行frpc,将vps的10001:20000转发到server1的1:10000端口,将vps的20001:30000转发到server2的1:10000端口。
如果有想要自建的朋友,建议阅读完全文再动手安装。
步骤 VPS端 下载FRP0.29.0 Release 并解压
wget https://github.com/fatedier/frp/releases/download/v0.29.0/frp_0.29.0_linux_amd64.tar.gz tar -zxf frp_0.29.0_linux_amd64.tar.gz mv frp_0.29.0_linux_amd64 frp

进入frp文件夹,编辑frps.ini
cd frp vim frps.ini

配置文件为:
[common] bind_port = 2221 max_pool_count = 5 log_level = error

绑定的端口2221需要在vps防火墙设置中放行UDP和TCP流量。
然后运行frps,进行测试:
./frps -c frps.ini

【Linux|【经验】使用FRP搭建内网穿透服务】和frpc测试连通(见下文)后,可以设置为service,实现自启动:
先修改service文件:
vim frp/systemd/frps.service

修改ExecStart的路径为实际frp解压路径,并且注意如果是以root用户执行,默认的User=nobody会出现错误,需要改为User=root。并注意以service执行的程序受到IO限制,无法打开太多端口,添加LimitNOFILE=65535以放宽限制。
[Unit] Description=Frp Server Service After=network.target[Service] Type=simple User=root Restart=on-failure RestartSec=5s ExecStart=/root/frp/frps -c /root/frp/frps.ini LimitNOFILE=65535[Install] WantedBy=multi-user.target

之后添加服务并设置为自启动
cp systemd/frps.service /lib/systemd/system/ systemctl daemon-reload systemctl enable frps systemctl start frps

这时可以使用systemctl status frps查看进程的PID,之后使用cat /proc/1238/limits确认Max open files项是否放宽为65535。
内网server端 下载FRP0.29.0 Release 并解压
wget https://github.com/fatedier/frp/releases/download/v0.29.0/frp_0.29.0_linux_amd64.tar.gz tar -zxf frp_0.29.0_linux_amd64.tar.gz mv frp_0.29.0_linux_amd64 frp

进入frp文件夹,编辑frpc.ini
cd frp vim frpc.ini

配置文件为:
[common] server_addr = vps的ip server_port = 2221 pool_count=2[range:server1_tcp] type = tcp local_ip = 内网server1的ip,可以是本机127.0.0.1,也可以是内网里其他server的ip如192.168.1.101 local_port = 1-10000 remote_port = 10001-20000[range:server1_udp] type = udp local_ip = 内网server1的ip,可以是本机127.0.0.1,也可以是内网里其他server的ip如192.168.1.101 local_port = 1-10000 remote_port = 10001-20000[range:server2_tcp] type = tcp local_ip = 内网server2的ip,可以是本机127.0.0.1,也可以是内网里其他server的ip如192.168.1.101 local_port = 1-10000 remote_port = 20001-30000[range:server2_udp] type = udp local_ip = 内网server2的ip,可以是本机127.0.0.1,也可以是内网里其他server的ip如192.168.1.101 local_port = 1-10000 remote_port = 20001-30000

先启动vps上的frps,再启动server上的frpc
./frpc -c frpc.ini

这时就可以通过vps ip:port+10000访问server1的ip:port,vps ip:port+20000访问server2的ip:port了。
因为实际使用frpc是在server的docker容器内,systemd自启动有些问题,所以目前frpc使用screen工具来后台运行:
screen -S frpcScreen ./frpc -c frpc.ini

然后按Ctrl+A Ctrl+D退出当前screen。
终止正在前台运行的frpc以及frps需要使用Ctrl+C组合键关闭,如果使用Ctrl+Z或者Break或者关闭ssh客户端的方式终止,则已经打开的端口无法解除占用,只能重启系统。
测试连通性 测试tcp连通性可以在内网server上运行python3 -m http.server 8888来启动一个http服务,然后访问http://vps ip:18888/测试是否能够打开网页。
测试udp连通性可以使用netcat这个工具包。
安装netcat
apt install netcat-openbsd

内网server运行udp监听:
nc -ul 8883

vps上连接netcat,注意这里是连接vps本机的18883端口,frp给转发到内网server的8883端口上:
nc -u 127.0.0.1 18883

之后类似于聊天工具,在任意一方输入字符并回车,另一方可以看到对方的输入,证明udp连接成功。
尾言 作者声称没有对于大范围的ip段映射进行优化,但实际测试映射20000个端口是可实现的。目前还需要继续观察是否存在性能和稳定性问题。

    推荐阅读