不用公网 IP,把内网服务安全发布到公网:ZeroNews 快速上手

文章目录

  • [不用公网 IP,把内网服务安全发布到公网:ZeroNews 快速上手](#不用公网 IP,把内网服务安全发布到公网:ZeroNews 快速上手)
    • 1、前言
    • 2、你可能也有这些痛点
    • [3、三分钟讲清楚 ZeroNews 在做什么](#3、三分钟讲清楚 ZeroNews 在做什么)
      • [3.1 三个关键概念](#3.1 三个关键概念)
      • [3.2 技术特点](#3.2 技术特点)
      • [3.3 与开源内网穿透(FRP)的区别](#3.3 与开源内网穿透(FRP)的区别)
    • [4、上手准备:注册与 Token](#4、上手准备:注册与 Token)
      • [4.1 注册入口](#4.1 注册入口)
      • [4.2 套餐/定价怎么理解(够用就行)](#4.2 套餐/定价怎么理解(够用就行))
    • 5、多平台安装
      • [5.1 Windows](#5.1 Windows)
      • [5.2 MacOS](#5.2 MacOS)
    • [6、一起构建你的第一个映射(最小可复现 Demo:Flask)](#6、一起构建你的第一个映射(最小可复现 Demo:Flask))
      • [6.1 简易代码](#6.1 简易代码)
      • [6.2 内网映射](#6.2 内网映射)
      • [6.3 前端界面操作](#6.3 前端界面操作)
    • 7、总结
    • 参考链接

🍃作者介绍:25届双非本科网络工程专业,阿里云专家博主,深耕 AI 原理 / 应用开发 / 产品设计。前几年深耕Java技术体系,现专注把 AI 能力落地到实际产品与业务场景。

🦅个人主页:@逐梦苍穹

✈ 您的一键三连,是我创作的最大动力🌹

不用公网 IP,把内网服务安全发布到公网:ZeroNews 快速上手

适用人群:开发联调、远程演示、NAS/家庭服务器远程访问、小团队临时对外开放内网服务

目标:10 分钟跑通「注册 → Agent 在线 → 创建 HTTPS 映射 → 外网访问」

1、前言

内网穿透的工具其实挺多的,但我自己的诉求一直很朴素:

  • 不想为了临时联调/演示去折腾路由器端口映射
  • 没公网 IP(或者公网 IP 太贵/太麻烦),但又确实需要"外网能访问"
  • 不想为了一个小需求再搭一整套 VPN / 自建转发服务器

这次看 ZeroNews(零讯),我觉得比较"对胃口"的点是:上手链路很短------基本就是 Token、Agent、映射 这三件事。

内网穿透产品我个人更愿意关注两类:要么是小团队做的"体验型产品"(往往更愿意打磨上手细节、性价比也可能更友好),要么是头部大厂做的"生态型产品"(能力更全)。

2、你可能也有这些痛点

  • 本地/内网服务别人访问不了:远程同事联调、客户演示、第三方回调(Webhook)一律卡住
  • 家里 NAS / Mac mini 当服务器:没公网 IP,或者还在用端口映射(暴露面大、风险高)
  • VPN / 自建 FRP:不是不能用,但配置/维护成本不低,而且对"临时需求"不友好

3、三分钟讲清楚 ZeroNews 在做什么

一句话理解:在内网机器上跑 Agent ,它会跟 ZeroNews 云端节点建立加密通道;你在控制台创建 映射(域名/端口 → 内网 IP:端口),外网就能访问你的内网服务了。

3.1 三个关键概念

  • Token:你在控制台生成的"绑定凭证",用于把 Agent 绑定到账号
  • Agent:安装在内网设备(Windows/macOS/Linux/Docker/NAS/路由器等)的客户端
  • 映射(域名/端口) :把公网访问地址和内网服务地址绑定起来;常见是 HTTPS 网站映射,也可以做 TCP(SSH/RDP/MySQL 等)

协议范围(官网/文档口径):至少覆盖 HTTPS / TCP,并在官网介绍中提到 HTTP/2、WebSocket、gRPC、UDP 等能力入口。

3.2 技术特点

  • 安全加密:TLS/HTTPS 保障数据传输安全。
  • IP 控制:支持访问黑白名单。
  • 多 Agent 多隧道:同一套餐服务支持绑定多个Agent,灵活调整设备接入
  • 集中管理:平台统一远程连接,无需其它工具。
  • 多协议 :支持多种协议(HTTPS/TCP/TLS
  • 无需公网 IP:适用任何公网环境,无需改动网络设置。
  • 云端配置:配置云存储,自动推送。
  • 一键迁移:故障时一键恢复配置。

3.3 与开源内网穿透(FRP)的区别

提到开源内网穿透,大家第一印象可能是FRP:https://github.com/fatedier/frp

那ZeroNews和FRP的区别是什么呢:

特性 ZeroNews 开源内网穿透 (如FRP)
类型 商业、SaaS 完全开源
易用性 ★★★★★ (极易) ★★☆☆☆ (需技术)
服务器 官方提供 自行搭建 (VPS)
安全 内建多重安全策略、IP黑白名单、鉴权认证、端到端加密等 自行配置与管理
成本 有免费版, 付费升级 服务器成本

如何选择

  • ZeroNews : 如果您是 普通用户/企业用户,不懂技术,追求快速搭建、稳定、安全、省心地访问内网资源(如NAS、家庭电脑),或者企业需要快速部署。
  • 选开源 FRP: 如果您是技术爱好者、开发者,拥有自己的服务器,希望完全掌控、有深度定制需求,且不介意投入时间和精力去学习和维护。

4、上手准备:注册与 Token

4.1 注册入口

注册登录后第一件事:在控制台创建 Token(后面 Agent 绑定要用)。

4.2 套餐/定价怎么理解(够用就行)

我建议先按"能不能跑通 + 是否长期用"来选:

  • 免费版:先把流程跑通(做简单网站发布/日常测试/页面浏览等)
  • 个人/团队版:主要差在映射/端口/Agent 数量、并发、带宽上限,以及一些治理能力(如 IP 访问控制、Basic Auth 等)是否开放

个人:

团队:

5、多平台安装

官方文档覆盖得比较全:

这里演示两个平台,Windows和macOS

5.1 Windows

先下载: https://download.zeronews.cc/windows/x64/zeronews-windows-x64-v2-3.0.2.zip

以管理员运行:

绑定token:

bash 复制代码
zeronews.exe set token 「这里复制粘贴你自己的token」

启动命令:

1、只能在前台运行,当 Dos 窗口关闭时,程序会退出:

bash 复制代码
zeronews.exe start

2、实现 zeronews 开机自启动,并保持程序在后台运行:

bash 复制代码
zeronews.exe start -d

查看效果:

5.2 MacOS

跟着执行下面命令:

macos Intel芯片用户:

bash 复制代码
mkdir -p /Applications/zeronews
cd /Applications/zeronews
curl  -o zeronews.tmp  https://download.zeronews.cc/macos/amd/zeronews
mv zeronews.tmp zeronews
chmod +x  zeronews
./zeronews set token 「这里复制粘贴你自己的token」

macos Apple芯片用户:

bash 复制代码
mkdir -p /Applications/zeronews
cd /Applications/zeronews
curl  -o zeronews.tmp  https://download.zeronews.cc/macos/arm/zeronews
mv zeronews.tmp zeronews
chmod +x  zeronews
./zeronews set token 「这里复制粘贴你自己的token」

其实就一个区别:

本质上是芯片架构的区别。


上述完成之后,就是启动环节了:

1、只能在前台运行,当 Dos 窗口关闭时,程序会退出:

bash 复制代码
./zeronews start

2、实现 zeronews 开机自启动,并保持程序在后台运行:

bash 复制代码
./zeronews start -d

6、一起构建你的第一个映射(最小可复现 Demo:Flask)

目标:把你电脑上的一个本地 HTTP 服务,通过 ZeroNews 变成"外网可访问的 HTTPS 地址"。

6.1 简易代码

先看整体结构:

requirements.txt:

bash 复制代码
Flask==3.0.0

templates/index.html:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flask测试页面</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }
        .container {
            background: white;
            border-radius: 12px;
            padding: 40px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.2);
            max-width: 600px;
            width: 100%;
        }
        h1 {
            color: #333;
            margin-bottom: 30px;
            text-align: center;
        }
        .info {
            background: #f5f5f5;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }
        .info p {
            margin: 8px 0;
            color: #666;
        }
        .btn {
            background: #667eea;
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 16px;
            margin: 10px 5px;
            transition: background 0.3s;
        }
        .btn:hover {
            background: #5568d3;
        }
        .result {
            margin-top: 20px;
            padding: 15px;
            border-radius: 8px;
            background: #f9f9f9;
            min-height: 50px;
        }
        .result.success {
            background: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }
        .result.error {
            background: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }
        .btn-group {
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Flask 服务测试</h1>
        <div class="info">
            <p><strong>服务地址:</strong> http://localhost:8888</p>
            <p><strong>状态:</strong> <span id="status">运行中</span></p>
        </div>
        <div class="btn-group">
            <button class="btn" onclick="testGet()">测试GET请求</button>
            <button class="btn" onclick="testPost()">测试POST请求</button>
        </div>
        <div id="result" class="result"></div>
    </div>

    <script>
        function showResult(data, isError = false) {
            const resultDiv = document.getElementById('result');
            resultDiv.className = 'result ' + (isError ? 'error' : 'success');
            resultDiv.innerHTML = '<pre>' + JSON.stringify(data, null, 2) + '</pre>';
        }

        async function testGet() {
            try {
                const response = await fetch('/api/test');
                const data = await response.json();
                showResult(data);
            } catch (error) {
                showResult({ error: error.message }, true);
            }
        }

        async function testPost() {
            try {
                const response = await fetch('/api/info', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                        message: '测试数据',
                        timestamp: new Date().toISOString()
                    })
                });
                const data = await response.json();
                showResult(data);
            } catch (error) {
                showResult({ error: error.message }, true);
            }
        }
    </script>
</body>
</html>

test-flask.py

python 复制代码
from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/test', methods=['GET'])
def test_api():
    return jsonify({
        'status': 'success',
        'message': 'Flask服务运行正常',
        'port': 8888
    })

@app.route('/api/info', methods=['POST'])
def info_api():
    data = request.get_json()
    return jsonify({
        'status': 'success',
        'received': data,
        'message': '数据接收成功'
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888, debug=True)

6.2 内网映射

由于程序绑定的是8888端口,这里就以8888端口为例:

先查看一下用法:

bash 复制代码
./zeronews --help

映射测试端口:

bash 复制代码
./zeronews add https 127.0.0.1:8888 ivtkupui0h.fy.takin.cc

然后启动一个demo示例:

此时访问https://ivtkupui0h.fy.takin.cc,如果你发现无法访问

则可能是你没有启动,漏执行了命令。

查看设备是否启动:

如果没有启动,则需要执行:./zeronews start或者是./zeronews start -d

可以正常访问了:

然后可以在Agent当中查看自己的设备信息:

到这里,你就成功上手了ZeroNews内网穿透的基本使用。

6.3 前端界面操作

其实上述提到的命令行绑定端口的操作,在官网也可以实现操作(比如我们绑定一个本地端口678,并且把刚刚的程序改为678端口来试一下)。

1、如果域名已经用了,记得新增域名端口:

2、点击"映射"-"添加映射":

配置端口:

配置成功了:

访问:https://xzltech.dy.takin.cc

可以看到效果。

7、总结

我对 ZeroNews 的整体感受更像是:它把"内网穿透"这件事做得更像一个可控的发布入口------尤其适合"临时暴露、快速验证、可随时关掉"的场景。

  • 适合:开发联调、远程演示、NAS 远程访问、小团队远程办公/运维
  • 不适合:需要完全离线/自托管、对链路可控性有极致要求且不接受 SaaS 控制面的场景

下文预告: 实际应用场景当中的内网穿透(如AI应用/AI应用开发

参考链接

相关推荐
xiatianxy3 小时前
云酷科技用智能化方案破解行业难题
人工智能·科技·安全·智能安全带
好多渔鱼好多3 小时前
【流媒体协议】RTSP / RTP / RTCP 协议全景介绍
网络·网络协议·rtp·rtsp·rtcp·ipc摄像头
石像鬼₧魂石4 小时前
139/445 端口(Samba 服务)渗透测试全流程总结与复习
运维·安全·ssh
合才科技4 小时前
【要闻周报】网络安全与数据合规 1-12
安全·web安全
蜂蜜黄油呀土豆4 小时前
计算机网络中的传输层:深入解析 TCP 协议
网络协议·tcp/ip·计算机网络·三次握手·网络排查
小五传输5 小时前
网闸怎么选?新型网闸凭安全高效,成企业优选方案
大数据·运维·安全
WLJT1231231235 小时前
电子元器件:智能时代的核心基石
大数据·人工智能·科技·安全·生活
五仁火烧5 小时前
HTTP 服务器
服务器·网络·网络协议·http
信安成长日记5 小时前
CNI研究https://sanj.dev/post/cilium-calico-flannel-cni-performance-comparison
安全