1. 为什么需要双服务内网穿透?
最近在帮朋友部署一个网页聊天应用时遇到了典型的内网穿透需求。这个应用同时包含普通HTTP网页服务和WebSocket长连接服务,前者负责展示聊天界面,后者处理实时消息传输。这种"一个应用,两种协议"的场景在实际开发中非常常见,但传统的内网穿透方案往往只考虑单一协议,导致WebSocket连接经常出现问题。
我最初尝试用常规的HTTP穿透配置,结果发现聊天页面能打开,但消息死活发不出去。折腾半天才明白,WebSocket虽然基于HTTP协议,但在建立连接后会升级为TCP长连接,需要特殊处理。这就是为什么我们需要专门针对Web+WebSocket双服务设计穿透方案。
frp作为一款开源的内网穿透工具,完美支持这种混合协议场景。它不仅能穿透HTTP/HTTPS流量,还能处理原始TCP/UDP连接,特别适合需要同时暴露Web接口和长连接服务的应用。下面我就以CentOS7环境为例,手把手带你完成从安装到配置的全过程。
2. 环境准备与frp安装
2.1 服务器基础环境检查
在开始前,请确保你的内外网服务器都满足以下条件:
- 操作系统:CentOS 7.x(内核版本3.10+)
- 已配置好SSH远程访问
- 拥有sudo或root权限
- 防火墙(firewalld)处于运行状态
可以用这些命令快速检查环境:
# 查看系统版本 cat /etc/redhat-release # 检查防火墙状态 systemctl status firewalld2.2 获取frp最新版本
截至我写这篇文章时,frp最新稳定版是0.52.3。建议始终使用最新版本,因为老版本可能存在安全漏洞。可以通过GitHub Release页面查看最新版本号:
wget https://github.com/fatedier/frp/releases/download/v0.52.3/frp_0.52.3_linux_amd64.tar.gz如果下载速度慢,可以尝试国内镜像源。下载完成后验证文件完整性:
sha256sum frp_0.52.3_linux_amd64.tar.gz # 对比官网提供的校验值3. 外网服务器配置(服务端)
3.1 基础文件准备
解压安装包后,服务端只需要保留两个文件:
tar -zxvf frp_0.52.3_linux_amd64.tar.gz cd frp_0.52.3_linux_amd64 rm -f frpc frpc.ini # 删除客户端文件3.2 服务端核心配置
编辑frps.ini时,有几个关键参数需要特别注意:
[common] bind_port = 7000 # 控制通道端口 vhost_http_port = 8080 # HTTP虚拟主机端口 vhost_https_port = 8443 # HTTPS端口 max_pool_count = 100 # 连接池大小 authentication_method = token # 认证方式 token = your_secure_token_123 # 建议使用复杂令牌这里我强烈建议修改默认端口并启用token认证,否则你的服务器可能成为肉鸡。曾经有次我没设token,第二天发现服务器被用来做代理转发,CPU直接跑满。
3.3 防火墙与SELinux设置
CentOS7的firewalld需要放行相关端口:
firewall-cmd --permanent --add-port=7000/tcp firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --permanent --add-port=8443/tcp firewall-cmd --reload如果启用了SELinux,还需要额外配置:
semanage port -a -t http_port_t -p tcp 8080 semanage port -a -t http_port_t -p tcp 84433.4 服务管理方案
生产环境推荐使用systemd管理服务。创建/etc/systemd/system/frps.service:
[Unit] Description=Frp Server Service After=network.target [Service] Type=simple User=nobody Restart=on-failure RestartSec=5s ExecStart=/usr/local/bin/frps -c /etc/frp/frps.ini [Install] WantedBy=multi-user.target然后启用服务:
systemctl daemon-reload systemctl enable frps systemctl start frps4. 内网服务器配置(客户端)
4.1 客户端文件准备
客户端需要保留的文件与服务端相反:
rm -f frps frps.ini # 删除服务端文件4.2 双服务配置实战
针对Web+WebSocket场景,frpc.ini需要分段配置:
[common] server_addr = your_server_ip server_port = 7000 token = your_secure_token_123 [web] type = http local_ip = 127.0.0.1 local_port = 80 custom_domains = chat.yourdomain.com [websocket] type = tcp local_ip = 127.0.0.1 local_port = 45635 remote_port = 45635这里有个坑要注意:WebSocket必须用TCP类型,不能用HTTP类型。我有次配置成HTTP类型,结果连接建立后10秒就断开,查了好久才发现协议类型不对。
4.3 客户端自启动方案
同样建议使用systemd,配置类似服务端。如果想用脚本管理,可以这样写启动脚本:
#!/bin/bash nohup ./frpc -c ./frpc.ini > ./frpc.log 2>&1 & echo $! > ./frpc.pid停止脚本:
#!/bin/bash kill -9 `cat ./frpc.pid` rm -f ./frpc.pid5. 高级配置与优化
5.1 负载均衡配置
当单个客户端性能不足时,可以用多个客户端做负载均衡。服务端配置:
[web] type = http local_port = 80 custom_domains = chat.yourdomain.com load_balance_group = web_servers load_balance_mode = roundrobin5.2 流量压缩与加密
对于敏感数据,建议启用加密和压缩:
[common] tls_enable = true protocol = wss # WebSocket Secure [websocket] use_compression = true5.3 连接保持策略
防止长连接意外断开:
[websocket] heartbeat_interval = 30 heartbeat_timeout = 906. 常见问题排查
6.1 连接建立失败
首先检查基础网络:
telnet your_server_ip 7000 netstat -tulnp | grep frp6.2 WebSocket频繁断开
可能是Nginx超时设置问题:
location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400s; }6.3 性能调优
对于高并发场景,调整内核参数:
echo "net.ipv4.tcp_max_tw_buckets = 20000" >> /etc/sysctl.conf echo "net.core.somaxconn = 65535" >> /etc/sysctl.conf sysctl -p在实际部署中,我发现WebSocket连接数超过500时,需要调整frpc的文件描述符限制:
ulimit -n 655357. 安全加固建议
7.1 端口防护策略
限制访问源IP:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="1.2.3.4" port protocol="tcp" port="7000" accept'7.2 日志监控方案
配置logrotate防止日志爆满:
/var/log/frp/*.log { daily missingok rotate 30 compress delaycompress notifempty create 640 root root }7.3 定期更新策略
建议设置自动检查更新:
#!/bin/bash NEW_VER=$(curl -s https://api.github.com/repos/fatedier/frp/releases/latest | grep tag_name | cut -d '"' -f 4) if [ "$NEW_VER" != "v0.52.3" ]; then echo "New version $NEW_VER available" # 添加更新逻辑 fi经过三个月的生产环境运行,这套配置成功支撑了日均2000+的在线聊天连接。最关键的收获是:WebSocket穿透一定要用TCP类型,且需要适当调整超时参数。当遇到性能瓶颈时,优先考虑增加客户端实例而非单纯提升服务器配置。