云原生之旅:TCP 穿透,轻松暴露内网服务到公网

需求

目标: 将内网kubernetes集群中的的自签名 TLS 服务(ArgoCD)通过公网域名 example.com:5002 对外可见。

方案

有两种可行的方案:

我选择了方案2作为本教程的示例: 采用 TCP 代理类型,直接透传 HTTPS 流量。该方案最大的优势是 无需 frp 处理自签名证书,保证了端到端的加密,简化了配置,推荐用于自签名或自定义 TLS 服务的暴露。

开始

步骤如下:

  1. 安装示例服务(可选)
  2. 在公网服务器安装frp的服务端二进制文件并编写服务端(frps)配置
  3. 在本地(内网)安装frp的客户端二进制文件并编写客户端(frpc)配置
  4. 启动服务端和客户端
  5. 测试内网服务通过公网地址访问是否可行

安装示例服务(基于 Kubernetes/Helm)

如果你的环境不支持LoadBalancer暴露内网服务,那么就需要修改helm的安装参数server.service.type参数,可以使用NodePort,或者也可以使用Ingress和Gateway

kubernetes的gateway示例,如果使用了gateway-api,那么server.service.type就可以保持默认的ClusterIP值, 这里使用HTTPRoute演示,有安全需求也可以使用TLSRoute

yml 复制代码
# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: argocd-gateway
  namespace: argocd
spec:
#  addresses:
#    - type: IPAddress
#      value: 192.168.3.106
  # 替换成你集群中实际安装的 Gateway Controller Class 名称
  gatewayClassName: cilium
  listeners:
    - name: server
      protocol: HTTP
      port: 443
---
# argocd-server-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: argocd-server
  namespace: argocd
spec:
  parentRefs:
    - name: argocd-gateway # 绑定到上面创建的 Gateway
  hostnames:
    - "argocd.app.com" # 替换成你的域名
  rules:
    - matches:
        # 需要匹配的路径
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: argocd-server
          port: 443 # 路由到 argocd server的端口

检查gateway和httproutes, 验证PROGRAMMED是否为True

sh 复制代码
kubectl get gateway,httproutes -n argocd
bash 复制代码
#!/usr/bin/env bash
# 启用 POSIX 模式并设置严格的错误处理机制
set -o posix errexit -o pipefail

# https://github.com/argoproj/argo-helm/tree/main

mkdir -pv /home/kubernetes/argocd
cd /home/kubernetes/argocd

#git clone --depth 1 https://github.com/argoproj/argo-helm.git
helm repo add argo https://argoproj.github.io/argo-helm
helm pull argo/argo-cd
tar -zxvf argo-cd-*.tgz

cat > new-values.yaml <<EOF
controller:
  replicas: 1

server:
  ## Argo CD server Horizontal Pod Autoscaler
  autoscaling:
    enabled: false
    minReplicas: 2

repoServer:
  autoscaling:
    enabled: false
    minReplicas: 2

applicationSet:
  replicas: 1

server:
  replicas: 1
  service:
    type: LoadBalancer
  ingress:
    enabled: false
    ingressClassName: nginx
    annotations:
      nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
      nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
#    extraTls:
#      - hosts:
#        - argocd.example.com
#        # Based on the ingress controller used secret might be optional
#        secretName: wildcard-tls
EOF

helm upgrade --install argocd \
./argo-cd \
-n argocd \
--create-namespace \
-f new-values.yaml

列出安装的信息

sh 复制代码
helm ls -n argocd

检查服务

确保每个Pod都是Running状态,目前安装的argocd是无状态应用,一般只需要确认为Running状态基本就可以判定为服务正常运行了

bash 复制代码
kubectl get po,svc,secret -n argocd

记录其内网 IP 及端口。本例子是192.168.3.107:443

等待Pod安装部署完成后,测试访问:

sh 复制代码
curl -k -v https://argocd.app.com

检查示例服务响应的状态码,200即为正常

frps服务器配置

  1. 下载公网服务器的frp二进制文件
bash 复制代码
os="linux"
arch="amd64"
version="v0.65.0"
wget https://github.com/fatedier/frp/releases/download/$version/frp_$version_$os_$arch.tar.gz
tar -zxvf frp_$version_$os_$arch.tar.gz
cp frp_$version_$os_$arch/* /usr/local/bin
  1. 编写配置
bash 复制代码
cat > frps-argocd-custom-tls.toml <<EOF
# 基础配置
bindAddr = "0.0.0.0"
bindPort = 7000          # frpc 客户端连接到 frps 的端口

# HTTP/HTTPS 虚拟主机端口(TCP 透传不需要,但保持默认配置以备将来使用)
vhostHTTPPort = 80
vhostHTTPSPort = 443

# Dashboard 配置 (可选,用于监控)
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"

# 认证配置
auth.method = "token"
auth.token = "YOUR_SECURE_TOKEN_FOR_FRP" # <--- 修改为一个安全的 Token
# 将 YOUR_SECURE_TOKEN_FOR_FRP 替换为一个随机字符串,frpc 需使用相同的值。

log.to = "./frps.log"
log.level = "info"
EOF

配置客户端

  1. 下载公网服务器的frp二进制文件,将os和arch改成你本地机器的系统架构
bash 复制代码
os="darwin"
arch="arm64"
version="v0.65.0"
wget https://github.com/fatedier/frp/releases/download/$version/frp_$version_$os_$arch.tar.gz
tar -zxvf frp_$version_$os_$arch.tar.gz
cp frp_$version_$os_$arch/* /usr/local/bin

该配置将内网的HTTPS 服务 (192.168.3.107:443) 映射到 frps 的 5002 端口上。

sh 复制代码
cat > frpc-argocd-custom-tls.toml <<EOF
# 您的 frps 服务器地址和端口
# 请根据您的实际 frps 部署地址进行修改
serverAddr = "apikv.com"
serverPort = 7000 # 假设您的 frps 监听在 7000 端口

#user = "your_argocd_user" # 可选,建议设置一个唯一标识
#loginFailExit = true

# 日志配置
log.to = "./frpc.log"
log.level = "info"
log.maxDays = 3

# 认证配置
#auth.method = "token"
#auth.token = "12345678" # **替换为您 frps 配置中实际的 token

# 传输配置
# 保持默认的 TLS 连接到 frps,增加安全性
transport.tls.enable = true
transport.protocol = "tcp"

# 代理配置
# --------------------------------------------------

[[proxies]]
# 代理名称,建议命名具有辨识度
name = "argocd_https_tcp"
# 使用 tcp 协议进行透传
type = "tcp"
# 内网 ArgoCD 服务器的 IP 和 HTTPS 端口
localIP = "192.168.3.107"
localPort = 443
# frps 服务器上监听的公网端口
remotePort = 5002

# 如果您希望增加一层加密和压缩,可以启用(但会增加 CPU 开销)
# transport.useEncryption = true
# transport.useCompression = false

# 可选:如果您的 frps 启用了健康检查或负载均衡
# healthCheck.type = "tcp"
# healthCheck.timeoutSeconds = 3
# healthCheck.maxFailed = 3
# healthCheck.intervalSeconds = 10
EOF

部署和访问步骤

  1. 修改 Token : 务必在 frps.toml 和 frpc.toml 中将 auth.token 替换为一个安全的、唯一的字符串。

  2. frps 部署 : 在公网服务器上启动 frps,启动不报错即为正常运行,日志文件配置在了当前目录下的frpc.log

    bash 复制代码
    frps -c ./frps-argocd-custom-tls.toml

    查看日志:

    sh 复制代码
    cat frpc.log

确保公网服务器的防火墙已放行 TCP 端口 7000 (frp连接) 和 5002 (内网服务端口) 。

  1. frpc 部署 : 在内网机器上启动 frpc,启动不报错即为正常运行,日志文件是日志文件配置在了当前目录下的frpc.log

    bash 复制代码
    frpc -c ./frpc-argocd-custom-tls.toml

    查看日志:

    sh 复制代码
    cat frpc.log
  1. 公网访问: 通过以下地址访问您的内网服务:

    arduino 复制代码
    https://example.com:5002

    如果你的服务使用的是 自签名证书,浏览器访问时会提示"证书不安全/隐私错误",这是正常的,有需要可以另行配置,继续访问即可。

参考资料

  1. github.com/fatedier/fr...
  2. 完整的frps示例: github.com/fatedier/fr...
  3. 完整的frpc示例:github.com/fatedier/fr...
相关推荐
系统集成-鹰翔20 分钟前
ERP推单数据库怎么备份:SQLite WAL模式下只复制db文件为什么可能漏任务
javascript·数据库·经验分享·后端
软件技术NINI1 小时前
基于SpringBoot和Vue的摇滚乐鉴赏网站
vue.js·spring boot·后端·spring·html·毕业设计·毕设
Tsuki_tl2 小时前
【总结】Redis五大数据类型应用场景及基本命令
数据库·redis·后端·缓存·缓存中间件·redis命令·redis 五大数据类型
后台模板学习2 小时前
Go Web开发中任务调度框架的源码解析与高可用实现方案
开发语言·后端·golang
系统集成-鹰翔2 小时前
ERP对接升级提示数据库迁移失败:SQLite逐版本事务到底回滚到哪一步
javascript·数据库·经验分享·后端
IT_陈寒2 小时前
深入理解SpringBoot:核心原理与最佳实践
前端·人工智能·后端
学长毕设2 小时前
基于SpringBoot的校园礼服租赁系统的设计与实现
java·spring boot·后端
Best_Liu~2 小时前
SpringBoot全局日期格式化
java·spring boot·后端
小蒜学长2 小时前
基于Django+Vue喵汪联盟宠物领养系统的设计与实现(代码+数据库+LW)
后端·python·django·宠物领养系统·流程规范化
Dwzun3 小时前
基于SpringBoot3+Vue3的油莎豆种植管理系统
java·前端·vue.js·spring boot·后端·python·计算机网络