🚀 使用 Docker Compose 部署 NPS(轻量级内网穿透工具:服务端 + 客户端)
🚀 使用 Docker Compose 部署 NPS 内网穿透服务
NPS 是一款轻量级、高性能、功能强大的内网穿透代理服务器,支持 TCP、UDP、SOCKS5、HTTP 等几乎所有流量转发。通过 Docker Compose 部署可以简化安装流程,提高部署效率。
📝 项目简介
NPS 是一款专为内网穿透设计的代理服务器工具,它通过 Web 界面提供可视化管理,让用户能够轻松配置和管理内网服务的外部访问。
核心特点:
- 多协议支持:支持 TCP、UDP、HTTP、HTTPS、SOCKS5 等多种协议转发
- Web 管理界面:提供友好的 Web 图形界面,方便配置和管理
- 高性能:轻量级设计,资源占用少,性能出色
- 全平台兼容:支持 Linux、Windows、macOS 等多种平台
- 安全可靠:支持流量加密、访问控制等安全特性
🔧 部署前准备
系统环境要求
- 操作系统:支持 Linux、Windows、macOS
- Docker 引擎:确保已安装 Docker 服务
- Docker Compose:版本 2.0+
- 硬件资源:
- 内存:至少 512MB
- 存储空间:至少 1GB 可用空间
环境检查
1.检查 Docker 服务状态
systemctl status docker
确保 Docker 服务处于 active (running) 状态
2.检查 Docker 版本
docker -v
3.创建部署目录
mkdir -p /home/compose/nps && cd /home/compose/nps
⚙️ 配置 Docker Compose
NPS 服务端配置
创建 docker-compose-nps.yml 文件:
services:
nps:
# NPS 服务端镜像(yisier1 优化版,稳定兼容 Docker)
image: yisier1/nps
container_name: nps # 容器名称,便于管理(如查看日志、重启)
restart: always # 容器退出后自动重启(保障服务稳定,避免断连)
volumes:
# 核心挂载:本地 ./conf → 容器 /conf(存储配置文件,必须挂载!)
- ./conf:/conf
# 时区同步:确保服务端日志时间与本地一致(避免时间错乱)
- /etc/localtime:/etc/localtime:ro
network_mode: 'host' # 关键!使用主机网络,直接监听服务端端口(避免端口映射冲突)
#privileged: true # 特权模式(默认关闭,仅特殊网络场景需开启,如修改路由)
接下来
在./conf子目录,创建对应的配置文件,文件必须存在否则启动失败。
1.创建 clients.json 文件:
{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":2,"VerifyKey":"qplcfr11qs0u95qh","Addr":"223.74.26.13","Remark":"","Status":true,"IsConnect":true,"RateLimit":0,"Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":0,"WebUserName":"","WebPassword":"","ConfigConnAllow":true,"MaxTunnelNum":0,"Version":"0.26.20","BlackIpList":[""],"CreateTime":"2025-10-17 07:55:30","LastOnlineTime":"2025-10-17 08:00:51"}
*#*
2.创建 hosts.json 文件,无需填写内容保持空白就好。
3.创建 nps.conf 文件:
# 应用名称
appname = nps
#Boot mode(dev|pro)
#runmode = dev
# 运行模式(dev开发模式|pro生产模式)
# 优化:生产模式关闭冗余调试输出,减少性能损耗
runmode = pro
#HTTP(S) proxy port, no startup if empty# HTTP(S)代理端口,留空则不启动
http_proxy_ip=0.0.0.0
http_proxy_port=20000
https_proxy_port=20001
https_just_proxy=true
#default https certificate setting# 默认HTTPS证书配置
https_default_cert_file=conf/server.pem
https_default_key_file=conf/server.key
##bridge## 桥接配置(TCP穿透核心)
# 桥接类型为TCP(符合需求)
bridge_type=tcp
# 桥接端口(确保无占用且防火墙放行)
bridge_port=20002
# 桥接监听IP(允许所有IP连接)
bridge_ip=0.0.0.0
# Public password, which clients can use to connect to the server
# After the connection, the server will be able to open relevant ports and parse related domain names according to its own configuration file.
# 客户端连接服务器的公共密钥
# 连接后服务器会根据配置开放端口和解析域名
public_vkey=123 # 建议修改为复杂密钥(如随机字符串)提升安全性
#Traffic data persistence interval(minute)
#Ignorance means no persistence
# 流量数据持久化间隔(分钟)
# 留空表示不持久化(减少磁盘IO,提升性能)
#flow_store_interval=1
# log level LevelEmergency->0 LevelAlert->1 LevelCritical->2 LevelError->3 LevelWarning->4 LevelNotice->5 LevelInformational->6 LevelDebug->7
# 日志级别(LevelEmergency->0 紧急 | LevelAlert->1 警报 | LevelCritical->2 严重 | LevelError->3 错误 | LevelWarning->4 警告 | LevelNotice->5 通知 | LevelInformational->6 信息 | LevelDebug->7 调试)
# 优化:降低日志级别,减少IO开销(视频流无需详细调试日志)
log_level=4 #7
# 日志文件路径(留空使用默认,避免额外IO)
#log_path=nps.log
#Whether to restrict IP access, true or false or ignore # 是否限制IP访问(true/false/留空)
#ip_limit=true
#p2p # P2P配置(暂不使用,保持注释)
#p2p_ip=127.0.0.1
#p2p_port=6000
#web # Web管理界面配置
# 管理域名(无需可留空)
web_host= #a.o.com
# 管理员账号(建议修改)
web_username=admin
# 管理员密码(强烈建议修改为复杂密码)
web_password=123
# 管理端口(确保安全)
web_port = 20003
web_ip=0.0.0.0
web_base_url=
# 不启用SSL(减少加密开销,非管理场景优先性能)
web_open_ssl=false
web_cert_file=conf/server.pem
web_key_file=conf/server.key
# if web under proxy use sub path. like http://host/nps need this.
# 若Web管理在代理子路径下(如http://host/nps)需配置
#web_base_url=/nps
#Web API unauthenticated IP address(the len of auth_crypt_key must be 16)
#Remove comments if needed
# Web API无验证IP地址(auth_crypt_key长度必须为16)
# 需启用时取消注释
#auth_key=test
auth_crypt_key =1234567812345678 # 建议修改为随机16位字符串
#allow_ports=9001-9009,10001,11000-12000
# 允许穿透的端口范围(优化:添加视频流常用端口,避免被拦截)
# 包含HTTP(80)、HTTPS(443)、RTSP(554)、RTMP(1935)等常见视频端口
allow_ports=80,443,554,1935,20000-20010
#Web management multi-user login # Web管理多用户登录
allow_user_login=false
allow_user_register=false
allow_user_change_username=false
#extension # 扩展限制(优化:全部关闭,避免限制视频流传输)
allow_flow_limit=false # 不限制流量(视频流需大流量)
allow_rate_limit=false # 不限制速率(避免视频卡顿)
allow_tunnel_num_limit=false # 不限制隧道数量
allow_local_proxy=false
allow_connection_num_limit=false # 不限制连接数(视频可能多连接)
allow_multi_ip=false
system_info_display=false # 关闭系统信息显示,减少资源占用
#cache # 缓存配置(TCP穿透无需HTTP缓存,保持关闭)
http_cache=false
http_cache_length=100
#get origin ip # 获取源IP(无需,关闭减少处理步骤)
http_add_origin_header=false
#pprof debug options # pprof调试(关闭,避免性能损耗)
#pprof_ip=0.0.0.0
#pprof_port=9999
#client disconnect timeout
#disconnect_timeout=60
# 客户端断开超时时间(优化:延长超时,减少视频流频繁重连)
# 原60秒→120秒,适应网络波动
disconnect_timeout=120
[!NOTE] 提示 上面的文件,allow_ports 开放了 80,443,554,1935,20000-20010 端口,创建TCP端口从20005开始,我只有一个服务要开放够用了。20010你按情况调大调小需要开放的数字。
4.创建 tasks.json 文件:
{"Id":19,"Port":20005,"ServerIp":"","Mode":"tcp","Status":true,"RunStatus":true,"Client":{"Cnf":{"U":"","P":"","Compress":true,"Crypt":true},"Id":2,"VerifyKey":"qplcfr11qs0u95qh","Addr":"223.74.26.13","Remark":"","Status":true,"IsConnect":true,"RateLimit":0,"Flow":{"ExportFlow":4703739,"InletFlow":4703739,"FlowLimit":0},"Rate":{"NowRate":15619},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":9,"WebUserName":"","WebPassword":"","ConfigConnAllow":true,"MaxTunnelNum":0,"Version":"0.26.20","BlackIpList":[""],"CreateTime":"2024-11-30 15:35:13","LastOnlineTime":"2025-10-15 05:36:20"},"Ports":"","Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Password":"","Remark":"","TargetAddr":"","NoStore":false,"IsHttp":false,"LocalPath":"","StripPre":"","ProtoVersion":"","Target":{"TargetStr":"192.168.0.3:5006","TargetArr":["192.168.0.3:5006"],"LocalProxy":false},"MultiAccount":null,"HealthCheckTimeout":0,"HealthMaxFail":0,"HealthCheckInterval":0,"HealthNextTime":"0001-01-01T00:00:00Z","HealthMap":null,"HttpHealthUrl":"","HealthRemoveArr":null,"HealthCheckType":"","HealthCheckTarget":""}
*#*
NPC 客户端配置
创建 docker-compose-npc.yml 文件:
services:
npc:
# NPS 客户端镜像(与服务端镜像同源,确保兼容性)
image: yisier1/npc
container_name: npc3 # 容器名称,可自定义(如多客户端区分)
restart: always # 客户端断连后自动重连,保障穿透稳定
network_mode: host # 使用主机网络,直接转发内网服务端口
# 核心命令:指定服务端地址假设为19*.*.1**.1**、VKey、连接类型(必须替换为你的服务端参数)
command: -server=19*.*.1**.1**:20002 -vkey=xlg1v6a05qtavd3w -type=tcp
# 命令参数说明:
# -server:服务端公网IP:通信端口(替换为你的服务端IP,默认端口20002)
# -vkey:客户端唯一验证密钥(从服务端Web界面生成,下文详述)
# -type:连接类型(tcp,无需修改)
关键配置说明
- 网络模式:使用
host网络模式简化网络配置 - 数据持久化:
./conf:/conf挂载确保配置数据持久化 - 重启策略:
always确保服务异常时自动重启 - 客户端参数:
server:NPS 服务端地址和端口vkey:客户端验证密钥type:连接类型(TCP/UDP)
关键配置说明(新手必看)
| 配置项 | 作用与注意事项 |
|---|---|
network_mode: 'host' |
服务端 / 客户端均需开启!避免 Docker 网络转发导致的端口冲突,确保直接监听主机端口(穿透效率更高)。 |
服务端 ./conf:/conf |
核心配置目录!删除此目录会丢失所有客户端、隧道配置,需定期备份(下文维护部分详述)。 |
客户端 command |
必须替换 server 和 vkey 为实际值!server 格式为「公网 IP:20002」,vkey 从服务端生成。 |
/etc/localtime:/etc/localtime:ro |
只读挂载本地时区文件,确保日志时间与本地一致,排查问题时更易追溯时间线。 |
🚀 启动与验证
启动 NPS 服务端
docker compose -f docker-compose-nps.yml up -d
验证服务端状态
-
检查容器运行状态
bash docker ps应该看到 nps 服务处于Up状态 -
查看服务日志
bash docker compose -f docker-compose-nps.yml logs -f -
访问 Web 管理界面
- 在浏览器中访问
http://你的服务器IP:8080 - 使用默认账号密码登录(admin/123)
启动 NPC 客户端
docker compose -f docker-compose-npc.yml up -d
验证客户端连接
-
检查客户端状态
bash docker ps | grep npc -
查看客户端日志
bash docker compose -f docker-compose-npc.yml logs -f -
在 NPS 管理界面验证
- 登录 NPS Web 管理界面
- 查看客户端列表,确认客户端在线状态
🚀 启动与验证2
(2)访问服务端 Web 管理界面
- 打开浏览器,输入
http://服务端公网IP:8080(如http://190.1.111.111:8080); - 首次登录使用 默认账号密码:
- 用户名:
admin - 密码:
123
- 用户名:
- 登录后强制跳转至「密码修改页面」,设置新密码(建议包含字母 + 数字 + 符号,如
NPS@2024!),避免默认密码泄露风险。
(3)添加客户端并获取 VKey(核心!)
- 密码修改完成后,进入主界面,点击左侧「客户端管理」→「新增客户端」;
- 填写客户端基础信息(仅需配置必填项):
- 客户端名称:自定义(如「家庭 NAS」「本地电脑」,便于区分多客户端);
- 备注:可选(如「映射 NAS 的 Web 服务」);
- 其他参数(如流量限制、过期时间):默认即可,新手无需修改;
- 点击「确定」,客户端列表中会新增一条记录,记录中的 「VKey」列 即为客户端连接所需的密钥(如用户配置中的
xlg1v6a05qtavd3w),复制此 VKey 备用。
2. 步骤 2:启动客户端并验证连接
(1)修改客户端配置并启动
- 内网设备操作:进入客户端部署目录,编辑
docker-compose.yml,将command中的server和vkey替换为实际值(服务端公网 IP+VKey); - 启动客户端容器:
cd /opt/nps-client
docker compose up -d
(2)验证客户端是否连接成功
方法 1:查看客户端容器日志(最直接)
# 查看客户端实时日志,按 Ctrl+C 退出
docker compose logs -f npc3
- 若日志显示
success connect to server或「连接服务端成功」,说明客户端已正常绑定服务端; - 若日志显示
connect server fail,需排查服务端端口是否开放、VKey 是否正确(下文常见问题部分详述)。
方法 2:服务端 Web 界面验证
- 回到服务端
http://服务端IP:8080→「客户端管理」; - 查看新增客户端的「状态」列,若显示「在线」,说明连接成功;若显示「离线」,需排查客户端配置。
🔌 基础配置与使用
NPS 服务端基础配置
- 修改默认密码
- 登录 Web 管理界面后立即修改默认密码
-
在客户端配置文件中修改
web_password参数 -
配置端口映射
# 在服务器防火墙开放所需端口
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT # Web 管理端口
iptables -A INPUT -p tcp --dport 8024 -j ACCEPT # 客户端连接端口
创建内网穿透隧道
- TCP 隧道配置
- 应用场景:SSH 访问、远程桌面、数据库连接
-
配置步骤:
- 在 NPS 管理界面进入"隧道管理"
- 添加 TCP 隧道,配置目标内网服务地址和端口
- 设置服务端监听端口
-
HTTP/HTTPS 隧道配置
- 应用场景:内网网站访问、微信公众号开发
-
配置步骤:
- 添加 HTTP/HTTPS 隧道
- 配置域名和内网目标地址
- 设置 SSL 证书(如需要)
-
SOCKS5 代理配置
- 应用场景:全局内网访问
- 配置步骤:
- 添加 SOCKS5 代理
- 设置监听端口
- 配置客户端使用 SOCKS5 代理
客户端管理
- 添加客户端
- 在 NPS Web 管理界面进入"客户端"菜单
-
点击"新增"创建客户端,记录验证密钥
-
客户端连接
# 使用 Docker 运行 NPC 客户端
docker run -d --name=npc --restart=always --net=host yisier1/npc -server=IP:PORT -vkey=密钥 -type=tcp
🔌 基础配置与使用2(核心:创建隧道映射内网服务)
客户端连接成功后,需在服务端创建「隧道」,将内网服务(如 Web、SSH、远程桌面)映射到公网,实现外网访问:
以「映射内网 Web 服务(端口 80)」为例,步骤如下:
1. 确认内网服务状态
确保内网客户端设备上的 Web 服务已启动(如本地 Nginx、NAS 的管理界面),且内网可访问(如在客户端设备上访问 http://localhost:80 能打开页面)。
2. 服务端创建 TCP 隧道
- 服务端 Web 界面 → 左侧「隧道管理」→「新增隧道」;
-
选择隧道类型为「TCP 隧道」(适配 Web、SSH 等 TCP 协议服务),填写关键配置:
配置项 说明与示例值 所属客户端 下拉选择已连接的客户端(如「家庭 NAS」) 隧道名称 自定义(如「NAS-Web-80」) 本地 IP 内网服务所在的 IP(客户端设备的内网 IP,如 192.168.1.100,本地服务填127.0.0.1)本地端口 内网服务的端口(如 Web 服务默认 80,SSH 默认 22) 服务端端口 公网映射端口(自定义未占用端口,如 8081,需提前开放此端口)其他参数 默认即可(如压缩、加密:新手无需开启,按需配置) -
点击「确定」,隧道列表中新增记录,状态显示「正常」即生效。
3. 外网访问内网服务
在外网设备(如手机流量、非内网电脑)的浏览器中输入:http://服务端公网IP:服务端端口(如 http://19*.*.1**.1**:8081)
- 若能打开内网 Web 服务页面,说明穿透成功;
- 若无法访问,需排查隧道配置(本地 IP / 端口是否正确)、内网服务是否启动、服务端端口是否开放。
🛠️ 维护与管理
日常维护操作
1.服务启停
# 停止服务
docker compose -f docker-compose-nps.yml down
# 启动服务
docker compose -f docker-compose-nps.yml up -d
2.数据备份
# 备份配置文件
tar -czf nps-backup-$(date +%Y%m%d).tar.gz ./conf
3.服务更新
# 更新服务端
docker compose -f docker-compose-nps.yml pull
docker compose -f docker-compose-nps.yml down
docker compose -f docker-compose-nps.yml up -d
监控与日志
-
查看实时日志
bash docker compose -f docker-compose-nps.yml logs -f -
监控资源使用
bash docker stats nps -
检查网络连接
bash netstat -tulpn | grep -E ':(8080|8024)'
🐛 常见问题排查
1. 无法访问 Web 管理界面
问题现象:浏览器访问 http://IP:8080 无响应
解决方案: - 检查防火墙设置:
# 开放 8080 端口
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
- 验证服务绑定:
netstat -tulpn | grep 8080
2. 客户端连接失败
问题现象:NPC 客户端无法连接服务端
解决方案: - 检查服务端端口开放:
# 开放客户端连接端口
iptables -A INPUT -p tcp --dport 8024 -j ACCEPT
- 验证客户端配置:
docker logs npc3
3. 隧道连接失败
问题现象:隧道已建立但无法访问内网服务
解决方案: - 检查内网服务状态 - 验证隧道配置的目标地址和端口 - 检查内网防火墙设置
4. 性能问题
问题现象:传输速度慢或连接不稳定
解决方案: - 检查服务器带宽使用情况 - 调整隧道压缩设置 - 考虑使用 P2P 模式(如支持)
5. 容器启动失败
问题现象:Docker 容器无法正常启动
解决方案: - 检查端口冲突:
netstat -tulpn | grep -E ':(8080|8024)'
- 验证目录权限:
chmod -R 755 ./conf
通过本教程,您应该已经成功部署并配置了 NPS 内网穿透服务。NPS 的强大功能和简单配置让它成为内网穿透的优秀解决方案。如果在使用过程中遇到其他问题,可以参考项目官方文档或社区支持资源。
🐛 常见问题排查2
1. 客户端连接失败(日志显示「connect server fail」)
-
原因 1:服务端 20002 端口未开放或被占用。解决:
- 服务端执行
sudo ufw status确认 20002 端口已允许; - 云服务器检查安全组是否添加 20002 端口入站规则;
- 检查端口是否被占用:
sudo lsof -i :20002,若占用则停止对应服务。 -
原因 2:客户端
command中的server或vkey错误。解决: -
确认
server格式为「公网 IP:20002」(无多余空格,IP 无误); - 回到服务端「客户端管理」,核对 VKey 是否与客户端配置一致(区分大小写)。
- 原因 3:客户端设备无法访问外网(或服务端公网 IP 不可达)。解决:客户端设备执行
ping 服务端公网IP,若无法 ping 通,排查内网网络(如路由器是否正常联网、有无防火墙限制)。
- 服务端执行
2. 服务端 Web 管理界面无法访问(ERR_CONNECTION_REFUSED)
-
原因 1:8080 端口未开放或服务端容器未启动。解决:
- 服务端执行
docker compose ps确认nps容器状态为「Up」; - 开放 8080 端口:
sudo ufw allow 8080/tcp,云服务器同步配置安全组。 - 原因 2:忘记修改后的管理员密码(或密码输入错误)。解决:重置服务端配置(会丢失所有客户端、隧道配置,谨慎操作):
- 服务端执行
# 服务端操作:停止容器 → 删除配置目录 → 重启容器(恢复默认账号密码 admin/123)
docker compose down
rm -rf ./conf
mkdir -p conf && sudo chmod 777 conf
docker compose up -d
3. 隧道创建成功但外网无法访问内网服务
-
原因 1:隧道配置的「本地 IP / 本地端口」错误。解决:
- 确认「本地 IP」是客户端设备的内网 IP(如
192.168.1.100,非服务端 IP); - 确认「本地端口」与内网服务端口一致(如 Web 服务是 80,而非 8080);
- 客户端设备执行
curl http://本地IP:本地端口,验证内网服务是否正常(若无法访问,先修复内网服务)。 - 原因 2:服务端「自定义代理端口」未开放。解决:开放隧道配置中「服务端端口」(如 8081):
sudo ufw allow 8081/tcp,云服务器同步配置安全组。
- 确认「本地 IP」是客户端设备的内网 IP(如
-
原因 3:客户端与服务端连接已断开(状态显示「离线」)。解决:客户端执行
docker compose restart重连,服务端确认客户端状态恢复「在线」后重试。
4. 隧道访问时出现「连接超时」(Timeout)
-
原因:内网服务未启动,或隧道转发的端口与服务端口不匹配。
解决: 1. 客户端设备启动内网服务(如
sudo systemctl start nginx启动 Web 服务); 2. 服务端「隧道管理」中,核对「本地端口」是否与内网服务实际端口一致(如 SSH 是 22,而非 2222)。
通过以上步骤,新手可快速搭建 NPS 内网穿透服务,实现外网访问内网的 Web、SSH、远程桌面等服务。如需探索更多功能(如 UDP 隧道、HTTP 域名绑定、流量限制),可参考 NPS 官方文档(注:官方为原版 NPS,Docker 部署逻辑一致)。