云原生之旅: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,或者也可以使用IngressGateway

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的端口

检查gatewayhttproutes, 验证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二进制文件,将osarch改成你本地机器的系统架构
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.tomlfrpc.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...
相关推荐
小蜗牛编程实录4 小时前
2.MySQL-Buffer Pool详解
后端
Moonbit4 小时前
月报 Vol.04 : 新增 async test 与 async fn main 语法,新增 lexmatch 表达式
后端·github·编程语言
oak隔壁找我4 小时前
Spring Boot Starter 详解
后端
我是天龙_绍4 小时前
整合Mybatis-Plus分页插件,并实现分页api方法
后端
Ray665 小时前
Spring循环依赖
后端
oak隔壁找我5 小时前
Spring Bean 配置详解
后端
aloha_5 小时前
es离线部署与配置
后端
我是天龙_绍5 小时前
用SpringMvc,实现,增删改查,api接口
后端
小蜗牛编程实录5 小时前
MAT分析内存溢出- ShardingSphere JDBC的缓存泄露问题
后端