
零信任网络后端认证鉴权【免费下载链接】zitiThe parent project for OpenZiti. Here you will find the executables for a fully zero-trust, programmable network OpenZiti项目地址https://gitcode.com/gh_mirrors/zi/ziti点击查看免费下载ziti-tunnel是 OpenZiti 生态中面向 Linux 主机的流量拦截客户端它截获主机上发往 Ziti 服务地址的出站传输层数据包并将这些流量通过 Ziti 零信任网络安全地代理到目标服务。本文以 ziti-tunnel README 为主体结合当前仓库的 Go 源码与打包脚本完整讲解配置文件结构、三种拦截模式tproxy、tun、proxy的原理与运维要点、内建 DNS 服务器的解析器接入方式以及如何将 ziti-tunnel 以系统服务形式部署。读完本文你将能根据宿主机的内核能力选型正确的拦截模式并独立完成配置、启动、DNS 接入与故障排查。一、ziti-tunnel 在 OpenZiti 中的定位与工作原理OpenZiti 是一个可编程的全零信任网络。ziti-tunnel承担其中的客户端入站流量截获职责它拦截出站传输层Transport Layer数据包——这些数据包的目的地址是某个 Ziti 服务的拦截地址intercept address——并将其代理进入 Ziti 网络最终由 Ziti 的路由与控制器体系把流量送达真正承载服务的后端。哪些服务会被代理完全由配置文件中身份identity的 app-wan 成员关系决定。ziti-tunnel的行为链条如下使用配置文件中的身份凭证与 Ziti 边缘控制器Edge Controller完成认证周期性地向控制器查询该身份被授权使用的服务列表每当发现新的可用服务就调用所选拦截模式intercept mode并把服务详情交由其处理。从仓库源码看这一查询并更新服务的机制由 tunnel/intercept/svcpoll.go 与 ziti/tunnel/root.go 中的OnServiceUpdate: serviceListener.HandleServicesChange回调共同实现服务刷新周期可通过--svcPollRate参数调整默认 15 秒。二、配置文件身份与边缘控制器的连接凭证当某个身份成功向 Ziti 边缘控制器完成注册enrollment后系统会生成一份配置文件。以下是一份ziti-tunnel接受的完整示例来自 README{ ztAPI: https://ziti-dev-controller01.localhost:1080/, versions: { api: 1.0.0, enrollmentApi: 1.0.0 }, id: { cert: file:///root/device01.3rdparty.client.cert.pem, key: file:///root/device01.3rdparty.client.key.pem, ca: file:///root/ziti-dev-ingress01.external.chain.cert.pem } }各字段含义ztAPI边缘控制器的 API 地址ziti-tunnel启动后即向该地址认证并拉取服务列表versions.api/versions.enrollmentApi身份注册时使用的 API 版本号记录在案以备兼容性判断id.cert/id.key/id.ca身份的三张证书文件路径均以file://URI 形式给出。其中cert为客户端证书、key为对应的私钥、ca为信任链证书三者共同构成向控制器证明身份所需的 X.509 凭证。这份配置可以由ziti-tunnel自身的enroll子命令生成。仓库自带的 SysV init 脚本 ziti-tunnel 展示了完整的注册流程当配置文件不存在时脚本读取 JWT 注册令牌并执行${ziti_dir}/bin/ziti-tunnel enroll --jwt ${jwtfile} --out ${cfgfile}即enroll --jwt 令牌文件 --out 配置文件注册成功后才会启动隧道进程。三、快速上手run 子命令与拦截模式自动选择ziti-tunnel通过子命令指定拦截模式常见用法为run子命令它会根据宿主机可用的内核驱动自动选择首选拦截模式。典型启动命令与日志输出如下$ sudo ziti-tunnel run ziti.json [ 0.000] INFO ziti/tunnel/intercept/tproxy.New: tproxy listening on 127.0.0.1:33641 [ 0.006] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.run: using tproxy interceptor ...在缺少iptables的主机上tproxy 拦截模式的初始化会失败ziti-tunnel随即尝试回退到 tun 拦截模式$ sudo ziti-tunnel run ziti.json [ 0.001] INFO ziti/tunnel/intercept/tproxy.New: tproxy listening on 127.0.0.1:37313 [ 0.001] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.run: tproxy initialization failed: failed to initialize iptables handle: exec: iptables: executable file not found in $PATH [ 0.009] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.run: using tun interceptor如果没有任何拦截模式能成功初始化进程将以 FATAL 日志退出$ sudo ziti-tunnel run ziti.json [ 0.000] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.run: tproxy initialization failed: failed to initialize iptables handle: exec: iptables: executable file not found in $PATH [ 0.001] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.run: tun initialization failed: failed to open tun interface (name, mtu0): ioctl failed with invalid argument [ 0.001] FATAL ziti/tunnel/cmd/ziti-tunnel/subcmd.run: failed to initialize an interceptor从源码看run命令在 ziti/tunnel/run.go 中被定义为Use: run config、Short: Auto-select interceptor其含义是为兼容旧版 ziti-tunnel 脚本而保留的自动选择入口同时它还兼容旧版调用方式run的第一个位置参数会被自动写入--identity标志_ cmd.Flag(identity).Value.Set(args[0])因此ziti-tunnel run ziti.json与ziti-tunnel --identity ziti.json run等价。该命令当前实现中先尝试初始化 tproxy 拦截器失败则记录日志当interceptor仍为空时输出 FATAL 并退出上述 README 展示的回退 tun 行为即为自动选择策略中除 tproxy 之外最优先的回退路径。四、拦截模式详解ziti-tunnel支持三种拦截模式下面逐一说明适用场景、原理与验证方法。tproxy 模式基于 iptables TPROXY 的内核级透明代理tproxy 是运行在安装了ip_tables内核模块的 Linux 内核上的首选拦截模式。可用以下命令确认内核是否具备该模块$ lsmod | grep ip_tables ip_tables 32768 5 iptable_filter,iptable_security,iptable_raw,iptable_nat,iptable_mangletproxy 模式会操纵路由表与防火墙规则因此需要NET_ADMINLinux 能力。示例中以sudo运行正是获得 NET_ADMIN 的最简单方式$ sudo ziti-tunnel --identity ziti.json tproxy [ 0.000] INFO ziti/tunnel/intercept/tproxy.New: tproxy listening on 127.0.0.1:33355 [ 0.010] INFO ziti/tunnel/dns.NewDnsServer: starting dns server... [ 2.018] INFO ziti/tunnel/dns.NewDnsServer: dns server running at 127.0.0.1:53 [ 2.018] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding ziti-tunnel.resolver.test 19.65.28.94 to resolver [ 2.033] INFO ziti/tunnel/dns.(*resolver).RemoveHostname: removing ziti-tunnel.resolver.test from resolver [ 2.096] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: starting tunnel for newly available service wttr.in [ 2.290] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding wttr.in 5.9.243.187 to resolver [ 2.300] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: service wttr.in not hostable [ 2.300] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: starting tunnel for newly available service ssh-scarey [ 2.570] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding scarey.io 169.254.1.1 to resolvertproxy 模式会在回环接口loopback上创建一个网络监听器端口号随机选择上例为 127.0.0.1:33355。被拦截的 Ziti 服务流量通过两种机制被引导到该监听器① 防火墙规则iptablesTPROXY iptables target 是 tproxy 模式的主要拦截手段。它能把数据包送交本地监听器却无需修改数据包的目的地址字段关于 TPROXY target 的详细原理可参见内核文档 tproxy.txt 与iptables-extensions(8)手册页。首先tproxy 拦截器会向 PREROUTING 链挂接一条新的 iptables 链$ sudo iptables -nt mangle -L PREROUTING | grep NF-INTERCEPT NF-INTERCEPT all -- 0.0.0.0/0 0.0.0.0/0随后为每一个被拦截的服务在该链中创建规则。可以查看正在生效的 tproxy 规则$ sudo iptables -nt mangle -L NF-INTERCEPT Chain NF-INTERCEPT (1 references) target prot opt source destination TPROXY tcp -- 0.0.0.0/0 5.9.243.187 /* wttr.in */ tcp dpt:443 TPROXY redirect 127.0.0.1:33355 mark 0x1/0x1 TPROXY tcp -- 0.0.0.0/0 169.254.1.1 /* ssh-scarey */ tcp dpt:22 TPROXY redirect 127.0.0.1:33355 mark 0x1/0x1 TPROXY tcp -- 0.0.0.0/0 1.2.3.4 /* netcat */ tcp dpt:22169 TPROXY redirect 127.0.0.1:33355 mark 0x1/0x1每条规则匹配目的地址 某 Ziti 服务的拦截地址的 TCP 数据包如wttr.in - 5.9.243.187:443并将之重定向到 ziti-tunnel 的网络监听器。由于所有服务都指向同一个监听器与同一个端口ziti-tunnel 只需一个监听器就能捕获发往任意地址的数据包。实现细节netfilter 为何被放弃README 明确指出实现 tproxy 模式时曾评估过更现代的 netfilter 方案——netfilter 有受支持的 netlink API无需shell out到iptables命令行工具。但 netfilter 的 tproxy 支持依赖内核配置项CONFIG_NFT_TPROXY与CONFIG_NFT_SOCKET而这两个选项在许多常见 Linux 发行版的默认内核中并未启用因此最终仍选用 iptables。tproxy 模式下ziti-tunnel会调用iptables可执行文件来维护规则这也是为什么 systemd 单元文件 中的注释特别说明tproxy 模式无法仅靠 capability 运行因为它要shell out到/sbin/iptables而iptables需要的CAP_NET_RAW不在其继承能力集中。② 本地路由Local RoutesTPROXY target 只在 iptables 的PREROUTING 链中有效而 PREROUTING 链只被经网络路由进主机的入站数据包遍历。要让本机生成的数据包也走 PREROUTING 链必须添加一条本地路由local route$ ip route show table local local 1.2.3.4 dev lo proto kernel scope host src 1.2.3.4 local 5.9.243.187 dev lo proto kernel scope host src 5.9.243.187 local 169.254.1.1 dev lo proto kernel scope host src 169.254.1.1ziti-tunnel被终止时其信号处理器signal handler会自动清理上述 iptables 规则与本地路由。从源码看tproxy 拦截器位于 tunnel/intercept/tproxy/其中 tproxy.go 为核心实现并通过tproxy_linux.go等平台文件隔离系统调用。tproxy子命令还支持两个高级标志见 ziti/tunnel/tproxy.go--lanIf指定一个或多个网卡接口被拦截服务地址的 INPUT 规则只分配给这些接口逗号分隔或重复使用该标志--diverter指定一个外部 tproxy 配置工具替代 ziti-tunnel 内建的 iptables 实现。tun 模式基于点对点地址的虚拟网卡tun 拦截模式会创建一个临时ephemeraltun 接口并把被代理服务的 IP 地址配置到该接口上。由于它操纵网络接口同样需要NET_ADMINLinux 能力示例中同样以 sudo 运行$ sudo ziti-tunnel --identity ziti.json tun [ 0.010] INFO ziti/tunnel/dns.NewDnsServer: starting dns server... [ 2.012] INFO ziti/tunnel/dns.NewDnsServer: dns server running at 127.0.0.1:53 [ 2.012] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding ziti-tunnel.resolver.test 19.65.28.94 to resolver [ 2.031] INFO ziti/tunnel/dns.(*resolver).RemoveHostname: removing ziti-tunnel.resolver.test from resolver [ 2.089] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: starting tunnel for newly available service wttr.in [ 2.280] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding wttr.in 5.9.243.187 to resolver [ 2.282] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: service wttr.in not hostable [ 2.282] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: starting tunnel for newly available service ssh-scarey [ 2.502] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding scarey.io 169.254.1.2 to resolver [ 2.505] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: service ssh-scarey not hostable [ 2.505] INFO ziti/tunnel/cmd/ziti-tunnel/subcmd.updateServices: starting tunnel for newly available service netcat [ 2.506] INFO ziti/tunnel/dns.(*resolver).AddHostname: adding netcat 1.2.3.4 to resolver ...ziti-tunnel添加到 tun 接口的地址均为**点对点point-to-point**地址$ ip addr show dev tun0 10: tun0: POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP mtu 65535 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 169.254.1.1/32 scope host tun0 valid_lft forever preferred_lft forever inet 169.254.1.1 peer 5.9.243.187/32 scope host tun0 valid_lft forever preferred_lft forever inet 169.254.1.1 peer 169.254.1.2/32 scope host tun0 valid_lft forever preferred_lft forever inet 169.254.1.1 peer 1.2.3.4/32 scope host tun0 valid_lft forever preferred_lft forevertun 接口本身分配一个链路本地地址本例为 169.254.1.1每个被拦截的服务则由一条点对点地址表示远端地址等于该 Ziti 服务的拦截 IP。tun 模式之所以使用点对点地址而非本地路由是因为如果使用本地路由路由到 tun 接口的数据包会被 Linux 网络协议栈接收进入协议栈处理而点对点地址能确保数据包被送到线上to the wire——对 tun 接口而言即当 ziti-tunnel 从 tun 接口读取数据时这些包会被它拾取并代理进 Ziti 网络。当ziti-tunnel退出时tun 接口及上面配置的全部地址都会被移除即使进程异常终止Linux 内核也会在创建它的进程终止时自动删除该接口。tun 拦截模式的实现在 tunnel/intercept/ 目录下与 tproxy 共享拦截器框架接口的生命周期管理则位于 tunnel/router/ 相关实现中。proxy 模式每服务一个监听器proxy 拦截模式为每个被拦截的 Ziti 服务各创建一个网络监听器。与 tproxy/tun 不同它不使用控制器下发服务定义而是直接在命令行上指定要拦截的服务及其监听端口$ ziti-tunnel --identity ziti.json proxy wttr.in:8443 ssh-scarey:2222 netcat:22169 [ 0.004] INFO ziti/tunnel/intercept/proxy.(*proxyInterceptor).Start: starting proxy interceptor [ 0.120] INFO ziti/tunnel/intercept/updateServices: starting tunnel for newly available service ssh-scarey [ 0.183] INFO ziti/tunnel/intercept/updateServices: service ssh-scarey not hostable [ 0.183] INFO ziti/tunnel/intercept/updateServices: starting tunnel for newly available service netcat [ 0.183] INFO ziti/tunnel/intercept/proxy.proxyInterceptor.runServiceListener: {addr[0.0.0.0:2222] service[ssh-scarey]} service is listening [ 0.203] INFO ziti/tunnel/intercept/updateServices: service netcat not hostable [ 0.203] INFO ziti/tunnel/intercept/proxy.proxyInterceptor.runServiceListener: {addr[0.0.0.0:22169] service[netcat]} service is listening [ 0.203] INFO ziti/tunnel/intercept/updateServices: starting tunnel for newly available service wttr.in [ 0.226] INFO ziti/tunnel/intercept/updateServices: service wttr.in not hostable [ 0.226] INFO ziti/tunnel/intercept/proxy.proxyInterceptor.runServiceListener: {addr[0.0.0.0:8443] service[wttr.in]} service is listening命令行语法为proxy 服务名:端口 服务名:端口 ...。所有网络监听器都绑定到本地网络接口0.0.0.0$ netstat -tnl | fgrep 0.0.0.0 Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:2222 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22169 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTENproxy 模式被定位为开发者工具由于它不操纵路由表、防火墙或网络接口因而在没有 root 权限的环境中最为实用。其实现位于 tunnel/intercept/proxy/proxy.go。五、内建 DNS 服务器与系统解析器配置ziti-tunnel默认运行一个内建 DNS 服务器它必须在主机解析器配置如 /etc/resolv.conf中排在最前面。启动时 ziti-tunnel 会执行一次自检self-test确保内建 DNS 服务器已接入系统解析器INFO[0002] dns server started on 127.0.0.1:53 INFO[0002] adding ziti-tunnel.resolver.test - 19.65.28.94 to resolver INFO[0002] removing ziti-tunnel.resolver.test from resolver自检过程是把一条已知的主机名/IP 映射插入内建 DNS 服务器再通过系统解析器去查询该主机名以确认解析链路真正生效。如果 DNS 自检失败ziti-tunnel 会直接退出ziti-tunnel will exit if the DNS self-test fails.。Linux 发行版通常会托管 /etc/resolv.conf 的内容直接编辑该文件只能短时生效很快会被托管进程覆盖。因此解析器配置改动必须能跨过 Linux 名称解析管理器的重启而持久存在。判断当前发行版使用哪种名称解析管理器最简单的方法是查看 /etc/resolv.conf$ ls -l /etc/resolv.conf如果 /etc/resolv.conf 是普通文件则很可能由dhclient管理如果 /etc/resolv.conf 是指向 /run/systemd/resolve 下文件的符号链接则由systemd-resolved管理。dhclient 发行版如果发行版使用 dhclient可在 /etc/dhcp/dhclient.conf 中加入以下内容让系统解析器优先使用 ziti-tunnel 的内建 DNS 服务器prepend domain-name-servers 127.0.0.1;然后重启网络管理器NetworkManager。如果不知道发行版对应的 NetworkManager systemd 服务名最稳妥的办法是直接重启主机。systemd-resolved 发行版在 systemd-resolved 的发行版上按如下步骤配置这也是仓库 ziti-tunnel.env 中RESOLVER_OPTSnone之外的手动接入方式$ sudo ln -sf /run/systemd/resolve/resolv.conf /etc $ echo -e [Resolve]\nDNS127.0.0.1 | sudo tee /etc/systemd/resolved.conf.d/ziti-tunnel.conf $ sudo systemctl restart systemd-resolvedhosts 文件兜底如果操作系统上的解析器无法由你控制ziti-tunnel 可以改用或更新hosts 文件来记录它隧道的所有主机名ziti-tunnel run --resolver file:///etc/hosts ${HOME}/ziti.json即通过--resolver file:///etc/hosts把解析后端切换为文件模式该模式实现在 tunnel/dns/file.go默认的 UDP 模式udp://127.0.0.1:53与服务器实现分别见 tunnel/dns/resolver.go 与 tunnel/dns/server.go。六、IP 地址分配机制当服务的地址是一个主机名时ziti-tunnel 会解析该主机名并把解析结果加入内建 DNS 服务器[0127] INFO adding myservice.mydomain.com - 45.60.32.165 to resolver如果服务的主机名无法解析ziti-tunnel 会寻找一个未使用的链路本地地址把它分配给该服务的路由[0012] INFO adding bogushost.net - 169.254.1.4 to resolver [0012] INFO ziti/tunnel/protocols/tcp.Listen: Accepting on 169.254.1.4:25 servicetelnet上述两条日志分别展示了两种路径可解析主机名进入内建 DNSdns.(*resolver).AddHostname不可解析主机名则分配169.254.1.x形式的链路本地地址。对于后者管理员还可通过--dnsSvcIpRange标志别名-d默认100.64.0.1/10自定义分配地址的 CIDR 范围——在 ziti/tunnel/root.go 的rootPreRun中该值会被提前读取并写入拦截器配置以确保 tproxy 等模式在安装本地路由前就拿到正确的地址段。七、以系统服务方式部署 ziti-tunnel仓库在 dist/dist-packages/linux/ziti-tunnel/deployment/ 下提供了两种 Linux 服务模板适合生产环境以守护进程方式运行。systemd 单元文件ziti-tunnel.service[Unit] DescriptionNetFoundry Ziti Tunnel Afternetwork-online.target [Service] EnvironmentFile/etc/systemd/system/ziti-tunnel.env ExecStart/opt/netfoundry/bin/ziti-tunnel --identity ${IDENTITY_JSON} --resolver ${RESOLVER_OPTS} ${INTERCEPT_MODE} Restartalways RestartSec1 [Install] WantedBynetwork-online.target配套环境文件 ziti-tunnel.env 定义了三项关键变量IDENTITY_JSON/opt/netfoundry/etc/ziti-client-identity.json RESOLVER_OPTSnone INTERCEPT_MODEtproxyIDENTITY_JSON身份配置文件的绝对路径RESOLVER_OPTS解析器选项示例值为noneINTERCEPT_MODE拦截模式示例值为tproxy可改为tun或proxy。单元文件中被注释掉的 capability 配置也值得注意CapabilityBoundingSetCAP_NET_ADMIN CAP_NET_BIND_SERVICE、ProtectSystemfull、ProtectHometrue等安全加固项之所以无法直接启用正是因为 tproxy 模式需要调用iptables详见本文 tproxy 一节的 netfilter 说明而iptables所需的能力不在其继承集中。SysV init 脚本ziti-tunnel 则提供了start|stop|restart|status子命令并内置了注册enroll逻辑若配置文件不存在且有 JWT 令牌文件则先执行ziti-tunnel enroll --jwt ... --out ...完成注册再启动进程它支持通过/etc/sysconfig/${service}注入VERBOSEYES与RESOLVER等环境变量日志写入/var/log/ziti-tunnel.logPID 记录于/var/run/ziti-tunnel.pid。八、从源码看实现命令结构与关键参数一览ziti-tunnel的命令树在 ziti/tunnel/root.go 中构建顶层tunnel命令旧版隐藏命令下挂载host、proxy以及按平台注册的run、tproxy等子命令rootPostRun中完成解析器创建dns.NewResolver、服务监听组ServiceListenerGroup装配与身份加载支持单身份--identity或身份目录--identity-dir。以下是 root 命令支持的常用全局参数源码即文档标志别名默认值说明--identity-i空已注册身份 JSON 文件的路径--identity-dir—空包含一个或多个已注册身份的目录自动加载其中所有 .json--verbose-vfalse开启调试级日志--svcPollRate—15服务更新轮询间隔秒proxy 模式除非显式设置否则不轮询--resolver-rudp://127.0.0.1:53解析器配置可用file:///etc/hosts切换为文件模式--dnsUpstream—无上游 DNS 服务器如udp://10.96.0.10:53、tcp://8.8.8.8:53可重复或逗号分隔--dnsUpstreamMode—parallel多上游查询方式parallel\|serial\|failover\|random--dnsUnanswerable—refused无法回答的 DNS 查询处置timeout\|servfail\|refused--dnsSvcIpRange-d100.64.0.1/10为不可解析的拦截主机名分配 IP 时的 CIDR 网段--log-formatter—终端 pretty日志格式json\|pretty\|text重定向时默认 json--cli-agent—true启用 CLI Agent供ziti命令远程管理--cli-agent-addr—空CLI Agent 监听地址如unix:/tmp/myfile.sock、tcp:127.0.0.1:10001--sdk-flow-control—true启用 SDK 流控--default-connections—2期望的默认连接数--control-connections—1期望的控制连接数tproxy子命令另有--lanIf拦截地址的 INPUT 规则限定的网卡列表与--diverter外部 tproxy 配置工具两个专属标志详见 ziti/tunnel/tproxy.go。结语ziti-tunnel的价值在于把零信任访问落地到普通 Linux 主机通过 tproxy 的内核级透明代理、tun 的点对点虚拟网卡或 proxy 的用户态监听业务应用无需任何改动即可把流量送进 Ziti 网络。选型建议可以概括为优先 tproxy要求内核有 ip_tables 且具备 NET_ADMIN不可用则回退 tun同样需要 NET_ADMIN 与 tun 设备支持无特权环境使用 proxy 并自行指定端口。配合内建 DNS 服务器的自检机制与正确的系统解析器配置即可在生产环境稳定运行。若需以守护进程方式托管直接采用仓库 deployment 目录 中现成的 systemd 单元或 SysV init 脚本是最快的落地路径。赞分享零信任网络后端认证鉴权【免费下载链接】zitiThe parent project for OpenZiti. Here you will find the executables for a fully zero-trust, programmable network OpenZiti项目地址https://gitcode.com/gh_mirrors/zi/ziti点击查看免费下载相关推荐RAP2 前端拦截插件指南jquery.rap.js 与 mock.rap.js 的两种 Mock 拦截模式深度解析RAP2 前端拦截插件指南jquery.rap.js 与 mock.rap.js 的两种 Mock 拦截模式深度解析 本指南围绕 RAP2 前端插件库 pu后端开发工具API设计Obliteration调试与测试使用GDB进行内核级调试的实用技巧Obliteration调试与测试使用GDB进行内核级调试的实用技巧 Obliteration是一款实验性的免费开源PlayStation 4内核项目为开发CAT 与 MyBatis 深度集成CatMybatisInterceptor 拦截器配置指南与源码解析CAT 与 MyBatis 深度集成CatMybatisInterceptor 拦截器配置指南与源码解析 导读 本文以 integration/mybatis可观测性指标监控告警APM后端链路追踪上一篇如何让AI自动玩2048游戏终极配置与使用指南下一篇如何让AI自动玩2048游戏新手快速入门终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考