虽然已经基于WireGuard将家里的本地网络同云服务器连接在了一起,但是由于内网穿透始终不是wg的强项,且一些情况下依旧需要P2P形式的内网穿透,所以目光就又回到了老朋友frp上来了,毕竟我的需求比较简单且frp用着习惯感觉也很稳定。

类似的内网穿透软件还有Ngrokn2n等,都是大同小异的中心服务器架构,区别在支持的功能以及是否有官方节点等服务。当然非官方的服务还是有挺多的,只是简单的用一用可以考虑。

frp的server即frps,需要部署在具备公网ip的环境下。回到Homelab的结构,一个master和worker都有公网ip,所以当然就要部署在这个公网worker上。

而在怎么把frps服务暴露出去这个问题上属实折腾了很久,说到底还是对k8s的service不理解所致。frps支持几乎常用的所有协议,基本使用情境下就仅聚焦于TCP、UDP以及HTTP就行了,其中HTTP视作TCP流量即可。集群ingress使用的是ingress-nginx,文档中提及可以做L4的lb,但是不推荐,尝试后发现一个的lb类型的ingress的svc仅可以支持一种协议,即TCP和UDP不能共存。随后查阅了traefikkongistio等,虽然有的具备L4负载均衡能力,但是都不是主责主业,且发觉并没必要增加那么多复杂性,尤其是istio还需要更改整个集群的CNI。回到service上来,service所支持的类型有LoadBalancer、ClusterIP、NodePort、ExternalName以及比较特殊的headless,headless主要是用于自定义服务负载均衡等这里不谈;LoadBalancer需要云服务商提供所以我也没有;ExternalName用来引入集群外部服务;ClusterIP将服务暴露给集群内部的其他服务,这种情况就可以使用ingress来均衡;NodePort将服务短裤暴露在每个node的指定端口上,访问地址即为NodeIP:SVC-Port

总结下来,就是把frps跑在集群的公网节点里并用NodePort形式暴露服务。同时对于frps暴露出来的http服务,需要配置ingress以供访问,这里可以利用到ingress的自动https进行加密,部署还是用helm v3。

添加helm repo

还是用了自建的helm repo:

1
2
helm repo add clemon https://helm-charts.clemon.icu
helm repo update

搜索下frps的chart:

image-20211126170729632

ok~出来了

修改配置并部署

  • frps监听端口位于frps.bind字段下,需同时配置pod上的端口和svc上的端口,映射的NodePort由k8s自动分配。
  • 对于http服务,frps.httpEndpoint.hosts字段下依次添加即可,注意host要写全。
  • 对于自定义端口的服务,在frps.ports字段下添加,映射的NodePort由k8s自动分配。
  • 服务端配置储存在config中,将配置写入frps.config字段下即可。注意部署后手动修改configMap不会痛不到本地的values.yaml,且手动修改后需要重启pod。

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
image:
repository: snowdreamtech/frps
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "latest"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

frps:
httpEndpoint:
podPort: 80
hosts: {}
# - host: "a.frp.example.icu"
# tls: true
# - host: "b.frp.example.icu"
# tls: true
# - host: "c.frp.example.icu"
# tls: false
ports: []
# - name: extPort-1
# podPort: 8089
# svcPort: 8089
# protocol: TCP
# - name: extPort-2
# podPort: 80891
# svcPort: 80893
# protocol: UDP
# - name: extPort-3
# podPort: 18089
# svcPort: 28089
dashboard:
enabled: true
ingress:
enabled: false
tls: false
host: "dashboard.frp.example.icu"
port: 7500
bind:
tcp:
pod: 7000
ing: 7000
# udp:
# pod: 7000
# ing: 7000
config:
mapName: ""
path: "/etc/frp/frps.ini"
content: |-
[common]
bind_addr = 0.0.0.0
bind_port = 7000
bind_udp_port = 7000
vhost_http_port = 7001
subdomain_host = frps
#dash board
enable_prometheus = true
dashboard_addr = 0.0.0.0
dashboard_port = 7000
# auth token
token = token123

serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""

service:
# for http endpoint
type: ClusterIP

ingress:
className: "nginx"
# 自动https
autoHttpsIssuer: "letsencrypt-prod"
annotations: {}

resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi

healthz:
enabled: true
livenessProbeOverride: {}
readinessProbeOverride: {}

nodeSelector:
network: public

部署

1
helm upgrade --install frps clemon/frps -n frps --create-namespace -f frps-values.yaml

image-20211126172128899

查看部署列表

image-20211126172426802

没有在ingress上暴露dashboard的话可以用kubectl port-forward来访问,NodePort暴露的端口可以在部署输出的信息里找到命令查找。

image-20211126172349029

截止写文章时,frps版本为0.38.0,添加了/healthz健康检查endpoint但是藏在dashboard的basic auth后面了就很尴尬,所以现在如果启用健康检查的话就不能开启dashboard的basic auth,提了Issue处理了这个问题,等下一个小版本就好了。

客户端连接

在本机起一个frpc,暴露一个http以测试

1
2
3
4
5
6
7
8
9
10
[common]
server_addr = example.com
server_port = 30437
token = token123

[ssh]
type = http
local_ip = 192.168.10.1
local_port = 80
subdomain = test

启动连接:

image-20211126173228357

访问:

image-20211126173337082

完美~