0%

Ferry 是什么呢

官网 https://ferryproxy.io/

源码地址 https://github.com/ferryproxy/ferry

Ferry 是为 Kubernetes 开发的一个多集群通信组件

Ferry 可以支持将一个集群的 Service 映射到另一个集群

快速开始

准备至少两个集群才能做演示

可以是一个节点的集群或者 Kind 起的集群但最少也要两个

下载 ferryctl

ferryctl 是 ferry 的安装运维工具

需要为每个集群的控制节点都安装一个 ferryctl

https://github.com/ferryproxy/ferry/releases

初始化控制面集群

1
2
# 在控制面集群执行
ferryctl control-plane init

向控制面声明哪个数据面需要加入

1
2
# 在控制平面执行,预连接其他数据平面
ferryctl control-plane join cluster-1

数据面做好被控制面管控的准备

上一个命令执行后, 会响应一个命令复制到数据面集群执行

控制面开始管控数据面

上一个命令执行后, 会响应一个命令复制到控制面集群执行

规则配置

测试应用需要提前部署并配置 Service

在控制面集群配置路由规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 映射 cluster-1 的 app-1.default.svc 映射到 control-plane 的 app-1.default.svc
apiVersion: traffic.ferryproxy.io/v1alpha2
kind: RoutePolicy
metadata:
name: ferry-rule
namespace: ferry-system
spec:
exports:
- hubName: cluster-1
service:
namespace: default
name: app-1
imports:
- hubName: control-plane
service:
namespace: default
name: app-1

Containerd 安装

1
2
3
4
5
6
VERSION=1.5.4
wget -c https://github.com/containerd/containerd/releases/download/v${VERSION}/containerd-${VERSION}-linux-amd64.tar.gz
tar xvf containerd-${VERSION}-linux-amd64.tar.gz -C /usr/local/
mkdir /etc/containerd/ && containerd config default > /etc/containerd/config.toml
wget -c -O /etc/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
systemctl start containerd

Nerdctl 安装

1
2
3
VERSION=0.11.0
wget -c https://github.com/containerd/nerdctl/releases/download/v${VERSION}/nerdctl-full-${VERSION}-linux-amd64.tar.gz
tar xvf nerdctl-full-${VERSION}-linux-amd64.tar.gz -C /usr/local/

主要记录一下自己写的拼凑 kubeconfig 的脚本
由于很难写成一个可定制化的东西, 当前先记录脚本按需求改改吧

使用 SA 的 Token

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
#!/usr/bin/env bash

# KUBECONFIG=you_kubeconfig ./generate_kubeconfig_with_sa.sh > new_kubecofnig

NAME=${NAME:-"readonly-kubeconfig"}
NAMESPACE=${NAMESPACE:-"default"}

kubectl apply -f - 1>&2 <<EOF
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: ${NAME}
namespace: ${NAMESPACE}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ${NAME}
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "get"
- "list"
- "watch"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ${NAME}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ${NAME}
subjects:
- kind: ServiceAccount
name: ${NAME}
namespace: ${NAMESPACE}
---
EOF

SECRET_NAME="$(kubectl get sa -n ${NAMESPACE} ${NAME} -o 'jsonpath={$.secrets[0].name}')"
CA_CRT="$(kubectl get secret -n ${NAMESPACE} ${SECRET_NAME} -o 'jsonpath={$.data.ca\.crt}')"
TOKEN="$(kubectl get secret -n ${NAMESPACE} ${SECRET_NAME} -o 'jsonpath={$.data.token}' | base64 --decode)"

APISERVER_ADDRESS=${APISERVER_ADDRESS:-"$(kubectl get cm -n kube-public cluster-info -o yaml | grep 'server: ' | sed 's/server: //' | sed 's/ *//g')"}

cat <<EOF
apiVersion: v1
kind: Config
current-context: ${NAME}
clusters:
- cluster:
certificate-authority-data: ${CA_CRT}
server: ${APISERVER_ADDRESS}
name: ${NAME}
contexts:
- context:
cluster: ${NAME}
user: ${NAME}
name: ${NAME}
users:
- name: ${NAME}
user:
token: ${TOKEN}
EOF

使用 CSR 签证书

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
#!/usr/bin/env bash

# KUBECONFIG=you_kubeconfig ./generate_kubeconfig_with_csr.sh > new_kubecofnig

NAME=${NAME:-"readonly-kubeconfig"}

openssl genrsa -out "${NAME}.key" 2048
CSR="$(openssl req -new -key "${NAME}.key" -subj "/CN=${NAME}" | base64 | tr -d '\n')"

kubectl delete csr "${NAME}" 1>&2

kubectl apply -f - 1>&2 <<EOF
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ${NAME}
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "get"
- "list"
- "watch"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ${NAME}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ${NAME}
subjects:
- kind: User
name: ${NAME}
apiGroup: rbac.authorization.k8s.io
---
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: ${NAME}
spec:
request: ${CSR}
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
---
EOF

kubectl certificate approve "${NAME}" 1>&2

CA_CRT="$(kubectl get cm -n kube-public kube-root-ca.crt -o 'jsonpath={$.data.ca\.crt}' | base64 | tr -d '\n')"
CLIENT_CRT="$(kubectl get csr "${NAME}" -o jsonpath='{$.status.certificate}')"
CLIENT_KEY="$(cat ${NAME}.key | base64 | tr -d '\n')"

APISERVER_ADDRESS=${APISERVER_ADDRESS:-"$(kubectl get cm -n kube-public cluster-info -o yaml | grep 'server: ' | sed 's/server: //' | sed 's/ *//g')"}

cat <<EOF
apiVersion: v1
kind: Config
current-context: ${NAME}
clusters:
- cluster:
certificate-authority-data: ${CA_CRT}
server: ${APISERVER_ADDRESS}
name: ${NAME}
contexts:
- context:
cluster: ${NAME}
user: ${NAME}
name: ${NAME}
users:
- name: ${NAME}
user:
client-certificate-data: ${CLIENT_CRT}
client-key-data: ${CLIENT_KEY}
EOF

生成 csr 的 -subj 的参数, CN 字段作为 User, O 字段作为 Group

使用 ca 私钥签证书

主体流程同上一个, 唯一不同的就是不再使用 k8s 的 CSR 资源签证书, 而是直接使用集群的 ca 私钥签. 对于权限需要较高, 不推荐使用.

工具

https://github.com/wzshiming/bridge

Docker 连接代理

1
2
# 代理远端的 docker 到本地的 2376 端口
bridge -b 'tcp://127.0.0.1:2376' -p 'unix:///var/run/docker.sock' -p nc: -p 'ssh://root@hostname?identity_file=~/.ssh/id_rsa'
1
2
# 设置环境变量, 新开终端执行 docker 命令
DOCKER_HOST=tcp://127.0.0.1:2376 docker ps

k8s 连接代理

1
2
# 代理远端的 k8s 到本地的 8000 端口
bridge -b 'tcp://127.0.0.1:8000' -p - -p 'ssh://root@hostname?identity_file=~/.ssh/id_rsa'
1
2
# 设置环境变量, 新开终端执行 kubectl 命令
ALL_PROXY=127.0.0.1:8000 kubectl get node

/etc/yum/vars/releasever

CentOS 7 静态 ip 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# cat /etc/sysconfig/network-scripts/ifcfg-ens192
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static # 这个标志着使用静态 ip
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens192
UUID=0e999030-a255-4221-a06e-2a6fd6677419 # 不同机子uuid一样(虚拟机克隆) 会互相顶掉, 可以用 uuidgen 重新生成
DEVICE=ens192
ONBOOT=yes
GATEWAY=10.7.0.1 # 网关
IPADDR=10.7.111.13 # ip
PREFIX=16 # 掩码位数
DNS1=114.114.114.114
ZONE=public

GitHub starsgithub.com/wzshiming/bridge

由于经常要 ssh 连接不同的服务器需要经过跳板机
ssh 的 ProxyCommand 使用不同协议使用不用的工具不同的语法格式
在多级代理上甚至不知道如何配置非常麻烦

写这个的初衷就是简化 ssh ProxyCommand 后面的命令格式以统一的格式处理不用的代理协议
后续发现可以写成一个通用的 tcp 代理

在监听端口的功能,一开始只支持 ssh ProxyCommand 的方式,使用 STDIO 和 ssh 通信
后面加上监听本地端口,甚至可以监听 ssh 服务器上的端口

支持的协议

  • http(s)-connect 拨号
  • socks4/4a 拨号
  • socks5/5h 拨号
  • ssh 拨号 & 监听

用法

映射 github.io:80 tcp 端口到本机的 8080 端口
由于是使用 ip 访问的 访问会返回 404 页面

1
bridge -b :8080 -p github.io:80

各种协议的代理

1
2
3
4
5
6
bridge -b :8080 -p github.io:80 -p ssh://username:password@my_server:22
bridge -b :8080 -p github.io:80 -p ssh://username@my_server:22?identity_file=~/.ssh/id_rsa
bridge -b :8080 -p github.io:80 -p socks5://username:password@my_server:1080
bridge -b :8080 -p github.io:80 -p http://username:password@my_server:8080
bridge -b :8080 -p github.io:80 -p 'cmd:nc %h %p'
bridge -b :8080 -p github.io:80 -p 'cmd:ssh sshserver nc %h %p'

多级代理

1
2
bridge -b :8080 -p github.io:80 -p http://username:password@my_server2:8080 -p http://username:password@my_server1:8080

监听 ssh 端口

也可以通过 ssh 监听端口 本地的端口映射到服务器的端口
由于 sshd 的限制只能监听 127.0.0.1 的端口
如果想提供对外的服务需要把 /etc/ssh/sshd_config 里的 GatewayPorts no 改成 yes 然后重新加载 sshd

1
bridge -b :8080 -b ssh://username:password@my_server:22 -p 127.0.0.1:80

用作 ssh 代理

更多的时候我是用作 ssh 代理的
在 ~/.ssh/config

1
ProxyCommand bridge -p %h:%p -p "ssh://username@my_server?identity_file=~/.ssh/id_rsa"

安装

1
2
# 安装
go get -v github.com/wzshiming/bridge/cmd/bridge

GitHub starsgithub.com/wzshiming/crun

通常的生成密码字典

用处很简单就是根据规则生成密码
但是使用十分麻烦

1
2
3
4
# 生成 最小为1,最大为6 在abcdefg中所有可能的组合
crunch 1 6 abcdefg
# 调用密码库 charset.lst, 生成最小为1,最大为8 所有可能的组合
crunch 1 8 -f charset.lst mixalpha-numeric-all-space

我第一想法为什么不能用 正则生成字典
谷歌度娘找了一圈可能真的没有
没有那就自己写一个呗

这个工具的生成密码字典

1
2
3
4
5
6
7
# 生成 1到6位长度的数字所有可能性组合
crun "\d{1,6}"
# 输出到 ditc.txt 文件
crun "\d{1,6}" > ditc.txt
# 暴力美学
crun "(root|admin):[0-9]{4,10}"
# !!!!! 注意如果量太大会超卡的

安装

1
2
# 安装
go get -v github.com/wzshiming/crun/cmd/crun

开始用 Hexo
搭建我的技术博客
养成写博客的习惯
之前的写的太丑放弃了好几次
新年新 Flag

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

按照惯例 helloworld

1
2
3
4
5
// main.c
#include <stdio.h>
int main() {
printf("Hello World!");
}
1
gcc main.c -o main && ./main