Compare commits

...

956 Commits

Author SHA1 Message Date
naison
fd59ed242c refactor: use origin workload of proxy mode (#621) 2025-06-04 14:30:24 +08:00
naison
a750327d9e hotfix: ignore some known top dns server on macOS 2025-06-04 06:26:09 +00:00
naison
69c5ed6c98 ut: add cache for setup minikube on macos 2025-06-03 17:23:37 +08:00
naison
d1dd44be35 ut: setup minikube on macos 2025-06-03 16:52:44 +08:00
fengcaiwen
229eb747a4 refactor: remove target-kubeconfig of clone mode 2025-06-02 19:05:36 +08:00
kubenetworks
dd3ba1c059 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-06-01 19:35:12 +08:00
wencaiwulue
db5ea99133 feat: update krew index version to refs/tags/v2.7.13 2025-06-01 19:34:43 +08:00
naison
fcbe2d64f7 chore: add ut for center install 2025-06-01 18:42:32 +08:00
fengcaiwen
a0c0860051 hotfix: fix center install cause mutate webhook not works 2025-06-01 18:39:02 +08:00
wencaiwulue
e374d6b51d feat: update krew index version to refs/tags/v2.7.12 2025-05-23 11:46:30 +08:00
kubenetworks
9703a12bc2 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-23 11:46:18 +08:00
naison
f9f52d1001 Merge pull request #612
ut: fix ut
2025-05-23 10:53:37 +08:00
naison
51c16989fe ut: fix ut 2025-05-23 02:52:37 +00:00
naison
75c609211b refactor: use informer to list&watch pod&service ip for adding to route table (#610) 2025-05-23 10:09:06 +08:00
naison
6d545dc5c9 hotfix: remove cidr if contains api-server ip 2025-05-20 22:12:19 +08:00
naison
b17da3cbcb feat: update krew index version to refs/tags/v2.7.11 (#607) 2025-05-18 17:32:49 +08:00
naison
d1108ebd86 Update charts/index.yaml (#608) 2025-05-18 17:32:35 +08:00
naison
792839a2d4 feat: support dump service into hosts in center cluster mode (#605) 2025-05-18 16:20:34 +08:00
fengcaiwen
f493931b41 hotfix: remove job before install 2025-05-18 16:20:13 +08:00
wencaiwulue
7df065ef93 feat: update krew index version to refs/tags/v2.7.10 2025-05-14 21:23:16 +08:00
kubenetworks
c265b3581c Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-14 21:23:03 +08:00
naison
f802e03d01 hotfix: add heartbeat to manager in the pod 2025-05-14 20:22:57 +08:00
wencaiwulue
c08cb461dd feat: update krew index version to refs/tags/v2.7.9 2025-05-12 17:18:47 +08:00
kubenetworks
1a2649a02a Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-12 17:18:34 +08:00
naison
facd6bdb3d hotfix: fix create temp kubeconfig but name container path separator (#599) 2025-05-12 16:28:15 +08:00
naison
a1117dee62 hotfix: handle not found route packet with gVisor instead of drop it 2025-05-12 15:49:40 +08:00
naison
b28eaef6a7 chore(mod): upgrade purego version to v0.8.3 2025-05-12 15:47:48 +08:00
naison
46aebef01f refactor: remove temp kubeconfig before daemon quit 2025-05-12 15:46:21 +08:00
naison
3791f48737 hotfix: fix create temp kubeconfig 2025-05-12 15:32:02 +08:00
wencaiwulue
fc76b70713 feat: update krew index version to refs/tags/v2.7.8 2025-05-11 00:17:22 +08:00
kubenetworks
e990dc1d0f Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-11 00:16:45 +08:00
naison
d636449073 feat: set read/write timeout to 60s for remote tcp conn (#590) 2025-05-10 23:02:31 +08:00
fengcaiwen
e85e1a6c40 refactor: show port-forward log 2025-05-10 18:05:44 +08:00
wencaiwulue
40d09716c4 feat: update krew index version to refs/tags/v2.7.7 2025-05-09 14:44:31 +08:00
kubenetworks
63792172bd Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-09 14:44:17 +08:00
naison
ca6a2be70f refactor: optimize get pod/service netowrk cidr logic (#585) 2025-05-09 13:06:32 +08:00
naison
e21fc8cda9 hotfix: duplicated definition of symbol dlopen on go1.23.9 2025-05-09 13:04:45 +08:00
wencaiwulue
1f4698c6f8 feat: update krew index version to refs/tags/v2.7.6 2025-05-08 10:09:00 +08:00
kubenetworks
efea780edf Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-08 10:08:49 +08:00
wencaiwulue
bdb21f8964 feat: update krew index version to refs/tags/v2.7.5 2025-05-07 17:00:00 +08:00
naison
e33d2f1928 hotfix: fix init dir 2025-05-07 16:08:56 +08:00
wencaiwulue
e6df115933 feat: update krew index version to refs/tags/v2.7.5 2025-05-07 10:36:28 +08:00
kubenetworks
549e56cd05 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-07 10:36:17 +08:00
fengcaiwen
54ed2b711f hotfix: fix init dir permission deny 2025-05-07 09:12:17 +08:00
wencaiwulue
56b81574ac feat: update krew index version to refs/tags/v2.7.4 2025-05-07 08:47:19 +08:00
kubenetworks
ce2b7a010e Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-05-07 08:47:05 +08:00
fengcaiwen
5df0c3ffdc hotfix: fix init dir permission deny 2025-05-07 00:17:35 +08:00
naison
8b0e87592a hotfix: fix init dir permission deny (#573) 2025-05-07 00:01:44 +08:00
naison
31a42c1fa7 feat: update krew index version to refs/tags/v2.7.3 (#571) 2025-05-06 23:55:53 +08:00
naison
ee0957a5c9 Update charts/index.yaml (#572) 2025-05-06 23:55:40 +08:00
naison
206d74c331 feat: use dns query as port-forward health check (#570) 2025-05-06 22:20:15 +08:00
naison
53ed72dee3 Merge pull request #567 from kubenetworks/refactor/refactor-code
refactor: refactor code
2025-04-29 22:16:59 +08:00
fengcaiwen
323235f268 refactor: optimize code 2025-04-29 21:53:34 +08:00
fengcaiwen
6af6622bd3 refactor: change server log level to info 2025-04-29 21:50:08 +08:00
fengcaiwen
18ef72fc20 refactor: forward only one port 2025-04-29 21:48:14 +08:00
fengcaiwen
fe08448249 refactor: split user and root daemon log 2025-04-29 21:40:46 +08:00
fengcaiwen
ebaa4098f1 refactor: change temp kubeconfig to ~/.kubevpn/tmp 2025-04-29 21:39:45 +08:00
fengcaiwen
9ba873494f feat: add heartbeats ping pod ip 2025-04-29 21:34:58 +08:00
naison
da40f3315b Merge pull request #566 from kubenetworks/hotfix/fix-bugs
hotfix: fix bugs
2025-04-27 23:19:40 +08:00
fengcaiwen
c4540b1930 refactor: use tcp conn instead of packet conn 2025-04-27 23:03:45 +08:00
fengcaiwen
a6ec321e46 hotfix: cmp running pod image tag and client version 2025-04-27 23:02:34 +08:00
fengcaiwen
79f8aca7df hotfix: close ssh session 2025-04-27 23:02:06 +08:00
fengcaiwen
6edfc3127d hotfix: quit sudo daemon before user daemon 2025-04-27 23:01:27 +08:00
naison
bed0a9168c Update charts/index.yaml (#564)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-04-25 23:40:24 +08:00
naison
d5ee35bfa8 feat: update krew index version to refs/tags/v2.7.2 (#563)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-04-25 23:39:56 +08:00
naison
9661a122bd refactor: optimize code (#561) 2025-04-25 19:37:03 +08:00
naison
28657e3832 refactor: remove deprecated options of config flags (#560) 2025-04-24 22:44:20 +08:00
naison
6a8a197f48 hotfix: close ssh client if ctx done (#559) 2025-04-24 22:41:24 +08:00
naison
31186fc1d9 refactor: only ssh jump in user daemon (#558) 2025-04-24 22:39:03 +08:00
naison
fca3baf47e refactor: optimize code (#557) 2025-04-23 15:00:00 +08:00
naison
1cae5d270b refactor: optimize ssh logic (#555) 2025-04-21 22:19:31 +08:00
naison
a3556a263d refactor: add additional [2]byte for packet length (#554) 2025-04-21 21:51:01 +08:00
naison
dd80717d8d refactor: return error if get nil daemon client (#553) 2025-04-20 15:49:03 +08:00
naison
537b2940fe perf: route packet by each tcp conn (#548) 2025-04-19 19:14:39 +08:00
naison
9aae88d54b hotfix: set recv/send buffer size 1024k for adding ip to route table on macos (#552) 2025-04-19 15:35:43 +08:00
naison
100a8df723 refactor: revert pr #517 (#551) 2025-04-19 12:35:09 +08:00
naison
48e30b4344 refactor: use go workspace for syncthing gui (#549) 2025-04-19 12:09:06 +08:00
naison
c9f1ce6522 chore: upgrade coredns version (#550) 2025-04-19 10:06:56 +08:00
naison
c42e3475f9 Update charts/index.yaml (#547)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-04-15 23:36:27 +08:00
naison
4fb338b5fc feat: update krew index version to refs/tags/v2.7.1 (#546)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-04-15 23:36:09 +08:00
naison
15243b3935 hotfix: remove closed conn from route map (#545) 2025-04-15 21:33:41 +08:00
naison
f0f9459976 hotfix: set mtu on windows (#544) 2025-04-15 21:32:47 +08:00
naison
ee7d5fa6f9 Update charts/index.yaml (#538) 2025-04-12 14:04:52 +08:00
naison
e393f8371e feat: update krew index version to refs/tags/v2.7.0 (#537)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-04-12 14:04:23 +08:00
naison
ca333fcdaf feat: encrypt with tls 1.3 (#522) 2025-04-12 12:30:05 +08:00
naison
7e4e9e1e0d refactor: add more log detect connect namespace (#536) 2025-04-12 10:53:27 +08:00
naison
58ee2df1a3 docs: add readme.md for helm charts (#534) 2025-04-11 22:06:00 +08:00
naison
15200f1caf refactor: add more log (#533)
* feat: add more log
2025-04-11 21:12:19 +08:00
naison
23baab449c refactor: optimize code (#531) 2025-04-11 19:13:06 +08:00
naison
0ddcaa8acc hotfix: fix bug (#530) 2025-04-11 19:12:15 +08:00
naison
0c122473ce hotfix: fix parse dig command output (#529) 2025-04-11 18:50:14 +08:00
naison
d08f74a57e hotfix: optimize code (#528)
* hotfix: optimize code
2025-04-10 22:53:28 +08:00
naison
cd66bb7907 feat: add log if drop packet (#527)
* feat: add log if drop packet
2025-04-09 22:19:37 +08:00
naison
f303616554 hotfix: fix []byte leak (#525) 2025-04-09 21:08:33 +08:00
naison
3973b85d25 hotfix: remove label (#524) 2025-04-08 22:02:07 +08:00
naison
4fd1f014bd refactor: adjust log level (#523) 2025-04-08 22:01:06 +08:00
naison
fe62cf6c4d hotfix: install missing command dig (#521) 2025-04-07 13:00:13 +08:00
naison
c5900d070c Update charts/index.yaml (#520)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-04-06 21:17:57 +08:00
naison
d84ca66cfb feat: update krew index version to refs/tags/v2.6.0 (#519)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-04-06 21:17:41 +08:00
naison
60c3030e65 hotfix: use echo instead of sysctl to set ipv4 ip_forward feature (#518) 2025-04-06 18:34:34 +08:00
naison
ea574a756b feat: support gcp auth (#517)
* feat: support gcp auth
2025-04-06 17:36:10 +08:00
naison
e8735a68be refactor: optimize logic (#515)
* refactor: optimize logic
2025-04-05 21:48:18 +08:00
naison
d55d290677 feat: update krew index version to refs/tags/v2.5.1 (#513)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-04-04 00:20:33 +08:00
naison
45435bcc48 Update charts/index.yaml (#514)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-04-04 00:04:07 +08:00
naison
dbe9f91ee0 hotfix: ut (#512)
* hotfix: ut
2025-04-03 23:00:03 +08:00
naison
b3d2e1e838 refactor: optimize code (#511) 2025-04-03 21:41:35 +08:00
yuyicai
fa0b343401 feat: change dockerfile (#491)
* feat: change dockerfile

Signed-off-by: yuyicai <yuyicai@hotmail.com>

* chore: change markfile for container test

Signed-off-by: yuyicai <yuyicai@hotmail.com>

* ut

* feat: install openssl

Signed-off-by: yuyicai <yuyicai@hotmail.com>

---------

Signed-off-by: yuyicai <yuyicai@hotmail.com>
Co-authored-by: naison <895703375@qq.com>
2025-04-03 21:10:31 +08:00
naison
a1bb338cdb refactor: optimize code (#510)
* refactor: rename
2025-04-03 20:51:55 +08:00
naison
dbc9df070b feat: add options netstack to helm charts (#509) 2025-04-03 20:45:12 +08:00
naison
804708aabe feat: add options --connect-namespace to proxy and dev mode (#508) 2025-04-03 20:44:59 +08:00
naison
21087fc708 hotfix: fix upgrade bug (#507)
* hotfix: fix upgrade bug
2025-04-03 20:44:43 +08:00
naison
94db7846d8 hotfix: fix detect helm ns but still use -n namespace (#506)
* hotfix: fix detect helm ns but still use -n namespace
2025-04-02 19:20:31 +08:00
naison
e205b77e41 Update charts/index.yaml (#505)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-03-31 14:02:55 +08:00
naison
2927261390 feat: update krew index version to refs/tags/v2.5.0 (#504)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-03-31 14:02:40 +08:00
naison
8f37488207 hotfix: fix upgrade logic (#503) 2025-03-31 12:50:10 +08:00
naison
d05a53a77f Update charts/index.yaml (#502)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-03-30 22:17:12 +08:00
naison
a2df9f7b59 feat: update krew index version to refs/tags/v2.4.3 (#501)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-03-30 22:14:33 +08:00
naison
cd68b1fb00 hotfix: gen envoy rule id by ns and resource uid (#500)
* hotfix: gen envoy rule id by ns and uid
2025-03-30 20:57:11 +08:00
naison
208f607f03 hotfix: fix dns slow (#499) 2025-03-30 11:56:57 +08:00
naison
116a1f1983 feat: detect namespace kubevpn installed by helm (#498) 2025-03-30 11:54:40 +08:00
naison
d191c927f4 feat: add helm to go mod (#497) 2025-03-30 11:52:21 +08:00
naison
a030dc582b feat: support connect one namespace but proxy workload in another namespace (#496) 2025-03-30 11:50:11 +08:00
naison
08bcbe1611 refactor: split connect and proxy mode (#495) 2025-03-30 11:46:37 +08:00
naison
fb428403a2 hotfix: set get running pod timeout 10s to 5s (#494) 2025-03-30 11:43:37 +08:00
naison
4f4bbd79f2 chore: optimize ut (#493)
* chore: optimize ut
2025-03-25 22:33:07 +08:00
naison
1ec3ca4637 hotfix: fix clone mode bug (#492) 2025-03-24 21:53:02 +08:00
yuyicai
484a5cafe4 Merge pull request #490 from kubenetworks/chart-releaser-qqesqc5oa54qow4n
Update index.yaml
2025-03-23 21:25:11 +08:00
yuyicai
b62a6b0185 Merge pull request #489 from kubenetworks/feat/update-krew-index-version
feat: update krew index version to refs/tags/v2.4.2
2025-03-23 21:24:34 +08:00
kubenetworks
90898c8047 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-03-23 12:53:36 +00:00
yuyicai
c06daf68e8 feat: update krew index version to refs/tags/v2.4.2 2025-03-23 12:52:53 +00:00
naison
d65da7ba66 chore(ut): add more ut (#475)
* chore: add more ut
2025-03-23 19:32:45 +08:00
naison
2ac187eb64 hotfix: delete old pod (#488) 2025-03-23 17:13:11 +08:00
naison
b46f7a9877 refactor: divide log to session and backend (#487)
* refactor: divide log to session and backend
2025-03-23 13:59:10 +08:00
naison
a5622b9439 chore: update sample bookinfo resource (#486) 2025-03-23 12:40:14 +08:00
yuyicai
0e8f655673 Merge pull request #483 from kubenetworks/docs-install-from-script
docs: install-from-script
2025-03-18 21:37:25 +08:00
yuyicai
f7250649af docs: install-from-script
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-18 20:54:47 +08:00
yuyicai
cbaff5e623 Merge pull request #481 from kubenetworks/install-kubevpn-by-shell-script
chore: install kubevpn by shell script
2025-03-17 22:30:02 +08:00
yuyicai
6aee9f0882 chore: install kubevpn by shell script
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-17 22:09:17 +08:00
yuyicai
1f63a15e01 Merge pull request #480 from kubenetworks/update-bookinfo-to-v1-20-2
chore: upgrade bookinfo to v1.20.2, add arm64 image
2025-03-17 22:05:44 +08:00
yuyicai
a65c26e446 chore: upgrade bookinfo to v1.20.2, add arm64 image
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-17 21:04:03 +08:00
naison
f5566f6ec2 feat: update krew index version to refs/tags/v2.4.1 (#478)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-03-16 17:55:36 +08:00
naison
543e2d716d Update charts/index.yaml (#479)
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
Co-authored-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-03-16 17:55:15 +08:00
naison
f267443c61 hotfix: delete pod force if check newer spec but have old env (#477) 2025-03-16 17:05:30 +08:00
naison
b6f90812f7 hotfix: restore service target port while leave resource in gvisor mode (#476) 2025-03-16 17:04:55 +08:00
naison
b5ea7b2016 chore: update github action (#474) 2025-03-14 22:24:32 +08:00
naison
30f904d7bb feat: update krew index version to refs/tags/v2.4.0 (#473)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2025-03-14 22:17:20 +08:00
kubenetworks
fde001009e Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-03-14 14:16:56 +00:00
naison
6908991461 refactor: optimize code (#472) 2025-03-14 21:12:11 +08:00
naison
031c2134d8 hotfix: also cleanup in user daemon if error occurs (#471) 2025-03-14 21:02:19 +08:00
naison
77570575ca refactor: upgrade deploy image if client version is incompatibility with image tag (#470) 2025-03-14 20:52:22 +08:00
Spongebob
a70ce62762 feat: add snap store release support (#469) 2025-03-14 19:23:41 +08:00
naison
5edd70452c feat: batch write route msg to unix socket: 'route ip+net: sysctl: no buffer space available' (#466) 2025-03-13 11:07:18 +08:00
naison
24d16b2791 hotfix: fix bugs (#468) 2025-03-13 11:04:49 +08:00
naison
6820dbb30d hotfix: do reverse opreation if operate cancelled (#465) 2025-03-12 18:36:12 +08:00
naison
ee26880bf5 refactor: use unix library to add route table and setup ip addr instead of use command route or ifconfig (#463) 2025-03-12 13:08:59 +08:00
naison
05b76094f0 feat: support service type externalName (#464) 2025-03-12 00:26:00 +08:00
yuyicai
2e79a331b4 Merge pull request #461 from kubenetworks/proxy-tun-arch-image
docs: add proxy tun arch image
2025-03-11 11:28:13 +08:00
yuyicai
ec5efc8253 docs: add proxy tun arch image
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-11 10:11:57 +08:00
naison
4547e84de9 Merge pull request #460 from kubenetworks/chore/update-bookinfo-resource
chore: update bookinfo resource
2025-03-10 22:00:30 +08:00
naison
f0694efeda Merge pull request #459 from kubenetworks/feat/extra-domain-support-ingress-record
feat: options extra-domain support ingress record
2025-03-10 19:39:18 +08:00
naison
8df6da1871 feat: options extra-domain support ingress record 2025-03-10 11:10:04 +00:00
yuyicai
ec7d939f8d Merge pull request #458 from kubenetworks/check-if-need-upgrade-server-image
feat: check if need to upgrade image
2025-03-09 16:28:03 +08:00
yuyicai
a682dfbc2c feat: check if need to upgrade image
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-09 16:01:56 +08:00
naison
a16c1ef007 Merge pull request #457 from kubenetworks/feat/setup-testcase-on-windows
feat: use kind instead of minikube on macos
2025-03-09 11:11:45 +08:00
naison
ec88fd82f0 feat: use kind on macos 2025-03-09 02:44:25 +00:00
yuyicai
3457a79328 Merge pull request #456 from kubenetworks/change-default-container-image
feat: change default container image
2025-03-09 10:29:58 +08:00
yuyicai
2780f67dd6 feat: change default container image
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-08 23:13:45 +08:00
naison
24b2195036 Merge pull request #455 from kubenetworks/chore/update-comment
chore: update comment
2025-03-07 17:06:47 +08:00
naison
d61d08694a chore: update comment 2025-03-07 09:04:10 +00:00
naison
f81c7ec3ce Merge pull request #454 from kubenetworks/feat/cmd-alias-support-env-KUBEVPNCONFIG
feat: cmd alias support env KUBEVPNCONFIG
2025-03-07 15:58:04 +08:00
naison
168db06979 feat: cmd alias support env KUBEVPNCONFIG 2025-03-07 07:57:06 +00:00
naison
8ad7463fc7 Merge pull request #453 from kubenetworks/hotfix/fix-cmd-ssh-npe
hotfix: fix cmd ssh resize terminal size npe
2025-03-07 15:38:18 +08:00
naison
8926577885 hotfix: fix cmd ssh resize terminal size npe 2025-03-07 07:37:39 +00:00
naison
0f94f58310 Merge pull request #452 from kubenetworks/refactor/optimize-code
refactor: optimize code
2025-03-07 10:54:40 +08:00
naison
210767d908 refactor: optimize code 2025-03-07 02:53:52 +00:00
yuyicai
ae9c23550f Merge pull request #451 from kubenetworks/build-ghcr-latest-container-image
chore: add ghcr.io latest container image
2025-03-07 09:29:36 +08:00
yuyicai
2f9a025f5b chore: add ghcr.io latest container image
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-06 22:18:01 +08:00
yuyicai
4d5c4fa426 Merge pull request #449 from kubenetworks/tun-ip-cidr
feat: change tun ip cidr
2025-03-06 21:31:28 +08:00
fengcaiwen
3a4bfa9241 feat: panic if parse network cidr error 2025-03-06 09:14:13 +08:00
yuyicai
db09cbbb6e feat: update tun cidr for kubevpn-traffic-manager
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-05 23:14:57 +08:00
yuyicai
a87cbf1e9a feat: change tun ip cidr
Signed-off-by: yuyicai <yuyicai@hotmail.com>
2025-03-05 22:27:43 +08:00
naison
547501fc41 Merge pull request #443 from kubenetworks/hotfix/fix-auto-upgrade-deploy-image
hotfix: fix auto upgrade deploy image
2025-02-25 22:25:00 +08:00
naison
7051f24313 hotfix: fix upgrade deploy image 2025-02-25 14:22:55 +00:00
naison
153fe3e5e7 Merge pull request #442 from kubenetworks/feat/update-krew-index-version
feat: update krew index version to refs/tags/v2.3.13
2025-02-23 22:32:32 +08:00
kubenetworks
78914e8765 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-02-23 14:30:35 +00:00
wencaiwulue
2fbfb080e0 feat: update krew index version to refs/tags/v2.3.13 2025-02-23 14:29:43 +00:00
naison
86585214d4 Merge pull request #438 from kubenetworks/hotfix/default-use-spdy-not-websocket-to-portforward
hotfix: default use spdy not websocket protocol to portforward
2025-02-23 21:42:21 +08:00
naison
867aefbc3a Merge pull request #441 from kubenetworks/hotfix/fix-daemon-process-unexpected-exit-on-linux
fix: fix daemon process unexpected exit on linux
2025-02-23 21:39:59 +08:00
fengcaiwen
2037d3b05f fix: fix daemon process unexpected exit on linux 2025-02-23 21:37:52 +08:00
naison
794fd861ba Merge pull request #440 from kubenetworks/hotfix/fix-podlabel-find-service-in-fargate-mode
use match not equal to find svc by pod label in fargate mode
2025-02-22 20:18:54 +08:00
naison
d10a4e3aef use match not equal to find svc by pod label in fargate mode 2025-02-22 12:00:56 +00:00
naison
5b39275f5b hotfix: default use spdy not websocket to portforward 2025-02-21 14:39:21 +00:00
naison
de38a35189 Revert "chore: upload charts to repo charts"
This reverts commit 2793ab20e6.
2025-02-13 10:40:33 +00:00
naison
04c0b33516 Merge pull request #436 from kubenetworks/feat/update-krew-index-version
feat: update krew index version to refs/tags/v2.3.12
2025-02-13 15:50:56 +08:00
kubenetworks
ffdefce23c Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-02-13 07:46:06 +00:00
wencaiwulue
2a3b4d89f7 feat: update krew index version to refs/tags/v2.3.12 2025-02-13 07:20:30 +00:00
naison
b1abafd7f4 Merge pull request #435 from kubenetworks/feat/add-cmd-image-copy
feat: add cmd image copy
2025-02-13 12:50:16 +08:00
naison
12f29f2528 Merge pull request #434 from kubenetworks/hotfix/fix-cmd-ssh-terminal-bug
hotfix: fix ssh terminal bug
2025-02-13 12:50:06 +08:00
naison
7f3f0305e4 feat: add cmd image copy 2025-02-13 04:48:39 +00:00
naison
c947472d47 hotfix: fix ssh terminal bug 2025-02-13 04:46:59 +00:00
naison
4013846cab Merge pull request #433 from kubenetworks/hotfix/use-default-krb5-config
hotfix: use default krb5 config and not cancel context after handle new local connection of PortmapUtil, otherwise ssh.client stop channel also closed
2025-02-13 11:48:14 +08:00
fengcaiwen
399bc4efe0 hotfix: not cancel context after handle new local connection of PortmapUtil, otherwise ssh.client stop channel also closed 2025-02-12 23:27:45 +08:00
fengcaiwen
24367b1b82 hotfix: use default krb5 config 2025-02-12 22:20:51 +08:00
naison
1a32d7a58e Merge pull request #432 from kubenetworks/chore/add-upload-charts-to-repo-charts
chore: upload charts to repo charts
2025-02-09 16:32:35 +08:00
naison
2793ab20e6 chore: upload charts to repo charts 2025-02-09 08:31:00 +00:00
naison
528ac55325 Merge pull request #431 from kubenetworks/chore/upgrade-go-mod-library
chore: upgrade go mod library
2025-02-09 11:19:10 +08:00
fengcaiwen
3896fd1642 chore: upgrade go mod library 2025-02-09 11:07:10 +08:00
naison
819b20bbdb Merge pull request #430 from kubenetworks/chore/upgrade-go-mod-library
chore: upgrade go mod library
2025-02-08 21:38:17 +08:00
fengcaiwen
2fc0bb3f0c chore: upgrade go mod library 2025-02-08 20:45:20 +08:00
naison
a6730613e7 Merge pull request #429 from kubenetworks/hotfix/add-platform-for-cmd-ssh
hotfix: add platform for cmd ssh
2025-02-08 20:12:06 +08:00
naison
3ad0b5d1a3 hotfix: add platform for cmd ssh 2025-02-08 12:04:25 +00:00
naison
3c2b7943b5 Merge pull request #427 from kubenetworks/feat/update-krew-index-version
feat: update krew index version to refs/tags/v2.3.11
2025-02-03 17:25:46 +08:00
kubenetworks
b2f5fc6ac1 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-02-03 09:24:54 +00:00
wencaiwulue
768e8b1931 feat: update krew index version to refs/tags/v2.3.11 2025-02-03 09:24:09 +00:00
naison
abe1bcafd6 Merge pull request #426 from kubenetworks/refactor/cmd-dev-use-exec-command-insead-of-library
refactor: dev mode use exec command instead of library
2025-02-03 14:21:55 +08:00
fengcaiwen
07cfb8b02e refactor: dev mode use exec command instead of library 2025-02-03 14:14:31 +08:00
naison
11a89d8609 Merge pull request #424 from kubenetworks/feat/use-regctl-copy-image-on-local-pc
feat: use regctl copy image on local pc
2025-01-29 14:05:47 +08:00
naison
98baec8253 feat: use regctl copy image on local pc 2025-01-29 06:03:36 +00:00
naison
1d40843e99 Merge pull request #423 from kubenetworks/docs/update-arch-image
docs: update arch image
2025-01-29 11:56:28 +08:00
naison
be327d571b docs: update arch image 2025-01-29 03:55:46 +00:00
naison
8c96431328 Merge pull request #422 from kubenetworks/refactor/logic-create-outbound-pod
refactor: create outbound pod
2025-01-25 21:51:37 +08:00
naison
666a69cdfb refactor: create outbound pod 2025-01-25 13:50:47 +00:00
naison
9a922ae084 Merge pull request #421 from kubenetworks/refactor/refactor-cmd-ssh-client
refactor: cmd ssh client
2025-01-25 20:28:42 +08:00
naison
f55a65e04c refactor: cmd ssh client 2025-01-25 12:27:51 +00:00
naison
a3c166dc7b Merge pull request #420 from kubenetworks/docs/update-gvsior-mesh-arch
docs: update gvisor mesh arch
2025-01-25 10:32:37 +08:00
naison
7426541e0f docs: update gvisor mesh arch 2025-01-25 02:28:27 +00:00
naison
d70ac3418e Merge pull request #418 from kubenetworks/feat/update-krew-index-version
feat: update krew index version to refs/tags/v2.3.10
2025-01-24 21:38:19 +08:00
kubenetworks
5c502c9d5f Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2025-01-24 13:36:35 +00:00
wencaiwulue
c7d8e381f4 feat: update krew index version to refs/tags/v2.3.10 2025-01-24 13:35:42 +00:00
naison
5ac2588e5d Merge pull request #417 from kubenetworks/docs/add-docs-gvisor-service-mode-proxy-arch
docs: add gvisor service proxy mode arch
2025-01-24 18:53:00 +08:00
naison
e0e45cf84e docs: add gvisor service proxy mode arch 2025-01-24 10:52:18 +00:00
naison
ebfb7168d2 Merge pull request #416 from kubenetworks/feat/add-image-pull-secret-name
feat: add image pull secret name
2025-01-24 14:53:06 +08:00
naison
caee039ffd feat: add image pull secret name 2025-01-24 06:51:34 +00:00
naison
3d4c8be963 Merge pull request #415 from kubenetworks/feat/not-realy-on-cap-net-admin-and-privliaged
feat: support AWS Fargate cluster
2025-01-18 21:26:04 +08:00
fengcaiwen
c6f59e46c9 hotfix: use pod label to match service selector for finding service by pod 2025-01-18 16:23:08 +08:00
fengcaiwen
7d028fc950 feat: proxy mode support proxy multiple workloads 2025-01-18 11:13:09 +08:00
fengcaiwen
12920650ba feat: aws fargate mode works 2025-01-18 11:10:20 +08:00
fengcaiwen
2e96247e74 feat: add cmd uninstall and rename cmd reset 2025-01-18 11:06:07 +08:00
fengcaiwen
b6cfba7db9 feat: fargate mode works basic 2025-01-18 10:52:51 +08:00
naison
8b771e82b5 docs: add supported by JETBRAINS (#411) 2025-01-05 20:25:41 +08:00
naison
d737a6b434 feat: update krew index version to refs/tags/v2.3.9 (#410)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-12-21 23:31:26 +08:00
kubenetworks
420fcd4abb Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-12-21 15:29:42 +00:00
naison
fd786caa0f hotfix: disable net.DefaultResolver.PreferGo (#409) 2024-12-21 22:51:03 +08:00
Constantin Revenko
d3c2ddecc4 return system resolver for sending requests to KubeAPI (#407)
Co-authored-by: Константин Ревенко <konstantin.revenko@mediascope.net>
2024-12-21 22:46:20 +08:00
naison
2e8d251b20 refactor: optimize alias output (#408) 2024-12-21 22:24:03 +08:00
naison
6cd7837d28 feat: update krew index version to refs/tags/v2.3.8 (#406)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-12-19 22:26:33 +08:00
kubenetworks
652a60ce1f Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-12-19 14:19:38 +00:00
naison
fad55dce28 feat(log): log trace if panic (#405) 2024-12-18 20:50:47 +08:00
naison
68d550a80d hotfix: use 64k buffer to read tun device packet for windows tun device mtu 65535 (#404) 2024-12-17 11:46:09 +08:00
Constantin Revenko
51166477c2 Fix panic when removing CIDRs containing API server IP addresses (#403)
* add func removeCIDRsContainingIPs

* remove comments

---------

Co-authored-by: Константин Ревенко <konstantin.revenko@mediascope.net>
2024-12-17 10:10:16 +08:00
naison
4476a38883 feat: update krew index version to refs/tags/v2.3.7 (#400)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-12-15 01:25:55 +08:00
kubenetworks
6597331740 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-12-14 17:25:08 +00:00
naison
6e594fa5a5 hotfix: ignore print cancel GRPC msg (#399) 2024-12-13 23:34:54 +08:00
naison
f046e474af hotfix: return error if resolve extra-domain ip is empty (#397) 2024-12-13 18:26:14 +08:00
naison
062c69de0e hotfix: add traffic-manager pod ip to route table (#396) 2024-12-13 18:21:01 +08:00
naison
b9c1f2a814 hotfix: fix print grpc msg bug (#395) 2024-12-13 18:16:20 +08:00
naison
5599dc6bdd refactor: optimize code (#393) 2024-12-11 21:04:09 +08:00
naison
d068125897 feat: update krew index version to refs/tags/v2.3.6 (#391)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-12-09 20:45:32 +08:00
kubenetworks
959d285294 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-12-09 11:52:05 +00:00
naison
d165dacd20 feat: use origin probe (#390) 2024-12-09 19:13:43 +08:00
naison
9ebc95352a hotfix: envoy control-plane detect enable ipv6 or not to add route (#389) 2024-12-09 18:50:44 +08:00
naison
d9d4091905 feat: update krew index version to refs/tags/v2.3.5 (#388)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-12-06 22:41:24 +08:00
kubenetworks
7618ae30ca Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-12-06 14:40:12 +00:00
naison
1dc3c057a7 hotfix: detect enable ipv6 for envoy (#387)
* hotfix: detect enable ipv6 for envoy

* hotfix: detect pod enable ipv6 for envoy

* hotfix: optimize code
2024-12-06 22:03:37 +08:00
naison
81f62eab31 refactor: refactor print GRPC message (#386) 2024-12-06 19:29:11 +08:00
naison
d9a978d330 hotfix: ignore setup ipv6 failed if not enable ipv6 (#385) 2024-12-05 15:05:54 +08:00
naison
c95cb5ba6c feat: update krew index version to refs/tags/v2.3.4 (#383)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-11-29 21:06:40 +08:00
kubenetworks
d418da83b0 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-11-29 13:03:24 +00:00
naison
24a97de5dc hotfix: add more resolver on macOS (#382) 2024-11-29 20:25:26 +08:00
naison
481b720da6 hotfix: close gvisor endpoint is tcp conn closed (#378) 2024-11-23 17:08:03 +08:00
naison
a1247995e7 feat: update krew index version to refs/tags/v2.3.3 (#377)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-11-22 22:54:56 +08:00
kubenetworks
7cb86d70b0 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-11-22 14:54:14 +00:00
naison
9edf0122a7 feat: alias add description (#376) 2024-11-22 22:09:35 +08:00
naison
5a0533c0fc feat: add gvisor endpoint log (#375) 2024-11-22 22:06:44 +08:00
naison
17a13a2672 hotfix: add idle timeout 120s for gvisor udp forwarder connection (#374) 2024-11-22 22:03:56 +08:00
naison
98c22ba9b7 refactor: refactor code (#373) 2024-11-22 22:00:50 +08:00
naison
880f842203 feat: update krew index version to refs/tags/v2.3.2 (#372)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-11-18 19:52:58 +08:00
kubenetworks
ab09f9e71c Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-11-18 11:52:12 +00:00
naison
ef16641675 refactor: refactor code (#371) 2024-11-18 18:47:54 +08:00
naison
d9a9000d7b hotfix: fix can not ping itself tun IP on windows 2024-11-18 10:43:59 +00:00
naison
a1212f5144 feat: update krew index version to refs/tags/v2.3.1 (#370)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-11-15 21:39:14 +08:00
kubenetworks
f4c22f3073 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-11-15 13:36:37 +00:00
naison
2aa7812cb1 feat: use gvisor parse network packet in pod (#369) 2024-11-15 20:56:10 +08:00
naison
cad5d23d33 feat: update krew index version to refs/tags/v2.2.22 (#367)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-10-30 16:52:55 +08:00
kubenetworks
85e8bd76d2 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-10-30 08:46:09 +00:00
naison
a243842052 hotfix: fix port-forward retry bug (#366) 2024-10-30 10:30:48 +08:00
naison
6e052a5a0b feat: logs lines support '-' sign means starting log file lines (#365) 2024-10-30 09:10:20 +08:00
naison
f966cd29d7 feat: add number of lines to logs (#364) 2024-10-29 18:44:41 +08:00
naison
bfb7ac441d feat: update krew index version to refs/tags/v2.2.21 (#362)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-10-25 22:41:23 +08:00
kubenetworks
0cc8b04bab Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-10-25 14:10:26 +00:00
naison
65ae890842 feat: add APIServer ip to route table if ssh info is not empty (#361) 2024-10-25 21:25:42 +08:00
naison
aa881a589e hotfix: fix ssh and port-forward retry bug (#360)
Co-authored-by: fengcaiwen <fengcaiwen@bytedance.com>
2024-10-25 21:25:03 +08:00
naison
07292fcde5 feat: update krew index version to refs/tags/v2.2.20 (#358)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-10-20 12:02:45 +08:00
kubenetworks
3071ff2439 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-10-20 04:00:07 +00:00
naison
a64eaf66da hotfix: fix port forward and ssh (#357)
* hotfix(portfoward): fix port-forward bug and ssh reconnect bug

* hotfix: remove larger overlapping cidrs for adding routes

* feat: retry port-forward if get pod err is not forbidden

* hotfix: fix ssh and port-forward

* feat: add more log

* hotfix: set go default revolver perfergo options to true
2024-10-20 11:23:49 +08:00
naison
9238e9914a feat(alias): show avaliable alias name (#354) 2024-10-18 16:15:35 +08:00
naison
6e4aeb288a hotfix: ssh daemon (#352) 2024-10-14 09:16:24 +08:00
wencaiwulue
105c3967e1 feat: update krew index version to refs/tags/v2.2.19 2024-10-10 12:12:34 +08:00
naison
5dae60ffbc hotfix: sleep 200ms reconnect 2024-10-10 11:35:39 +08:00
wencaiwulue
875cb8dc8c feat: update krew index version to refs/tags/v2.2.19 2024-10-10 11:07:19 +08:00
naison
15103837a7 hotfix: fix ssh re-connect logic 2024-10-10 10:28:58 +08:00
wencaiwulue
baf5b79a24 feat: update krew index version to refs/tags/v2.2.19 2024-10-10 08:48:44 +08:00
kubenetworks
5618500e66 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-10-10 00:47:09 +00:00
fengcaiwen
d28096d9fa hotfix: upgrade github action 2024-10-10 08:11:43 +08:00
fengcaiwen
bc960987ea hotfix: set version to tag if commitid is empty in github action workflow 2024-10-09 23:14:24 +08:00
fengcaiwen
1005075367 feat: upgrade go version in Dockerfile 2024-10-09 22:06:46 +08:00
fengcaiwen
8f4de1968a feat: upgrade dlv 2024-10-09 22:04:54 +08:00
fengcaiwen
a93f0b1667 feat: upgrade github action 2024-10-09 21:57:44 +08:00
fengcaiwen
941373a902 feat: upgrade syncthing gui 2024-10-09 21:50:32 +08:00
naison
605fe047ca feat: upgrade syncthing version 2024-10-09 21:50:32 +08:00
naison
4d075b29b3 feat: upgrade go version to 1.23 2024-10-09 21:50:32 +08:00
naison
d141ec869b fix: fix dns on linux (#336)
* fix: fix dns on linux

* feat: detect run in Github action or not to setup DNS
2024-10-09 19:17:50 +08:00
naison
e2757d3916 hotfix: fix setup docker failed on macos (#334) 2024-10-08 10:37:53 +08:00
naison
9d917ae9cb docs: update doc (#333) 2024-09-14 20:01:58 +08:00
naison
0763e8a201 hotfix: fix upgrade on windows (#330)
* hotfix: fix upgrade on windows
2024-09-13 14:12:04 +08:00
naison
274116e44f feat: update krew index version to refs/tags/v2.2.18 (#329)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-09-10 17:57:33 +08:00
kubenetworks
ed375be157 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-09-10 09:39:12 +00:00
naison
be8ef7a127 hotfix: use pro-bing to send heartbeats instead of genereating icmp packet (#328) 2024-09-10 16:56:25 +08:00
naison
2bfa82d936 docs: update readme.md (#327) 2024-09-08 15:37:18 +08:00
naison
394bc1a0e4 chore: add link to install tools (#326) 2024-09-07 09:26:20 +08:00
naison
e64b9a3311 feat: use scoop to install kubevpn on Windows (#325) 2024-09-07 08:44:37 +08:00
naison
f9bbaeb3cf chore: update command usage (#324) 2024-09-06 21:28:35 +08:00
naison
ac918b5009 feat: update krew index version to refs/tags/v2.2.17 (#319)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-08-03 16:54:54 +08:00
naison
69b6fa6318 hotfix: fix interface conversion panic (#318) 2024-08-03 16:05:33 +08:00
kubenetworks
63be89bf25 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-08-03 07:45:55 +00:00
naison
c4fb3c5ca0 refactor: remove useless heartbeats (#316) 2024-08-03 15:14:43 +08:00
naison
947d50af85 feat: add syncthing re-connect (#315) 2024-08-03 15:02:48 +08:00
naison
0826f2e20c refactor: refactor log make it more formal (#314) 2024-08-03 15:01:16 +08:00
naison
9f62e02f96 hotfix: use pod ip as dns server if service ip is unreachable (#313) 2024-08-02 12:07:10 +08:00
naison
a3b8c1586d refactor: refactor ssh structure (#311) 2024-07-27 10:37:48 +08:00
naison
675ce2a52f feat: update krew index version to refs/tags/v2.2.16 (#310)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-07-26 22:09:06 +08:00
kubenetworks
79e524e319 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-07-26 13:43:50 +00:00
naison
49adeac14c refactor: refactor command dev (#309) 2024-07-26 21:11:59 +08:00
naison
9283c2f8f7 refactor: shrink dev mode container options (#308) 2024-07-25 16:42:21 +08:00
naison
a48750c048 hotfix: fix clone sync init no permission (#307) 2024-07-24 18:44:15 +08:00
naison
bbf3914f1e hotfix: fix upgrade (#305) 2024-07-23 20:54:06 +08:00
naison
f13e21a049 refactor: refactor code (#306) 2024-07-23 19:11:58 +08:00
naison
a37bfc28da hotfix: fix upgrade use rename but cross device (#304) 2024-07-21 21:08:17 +08:00
naison
862238f65f feat: update krew index version to refs/tags/v2.2.15 (#301)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-07-19 23:03:54 +08:00
kubenetworks
18d6f67a5d Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-07-19 15:03:14 +00:00
naison
4ae09a9dd2 refactor: remove useless code (#300) 2024-07-19 22:28:58 +08:00
naison
1feaacaba9 refactor: refactor code (#299) 2024-07-19 22:25:23 +08:00
naison
bc7d205695 refactor: refactor DHCP logic (#298) 2024-07-19 22:07:35 +08:00
naison
78de74bf08 feat: enable tun ip forward on Windows (#297) 2024-07-19 22:06:14 +08:00
naison
8c0f2098c9 feat: update krew index version to refs/tags/v2.2.14 (#296)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-07-12 23:29:48 +08:00
kubenetworks
44320a792e Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-07-12 15:24:28 +00:00
naison
0e2a8f1ce6 feat: exec and port-forward using websocket if available (#295) 2024-07-12 22:09:50 +08:00
naison
b0a6a0d054 hotfix: fix ssh bug (#294) 2024-07-12 22:08:17 +08:00
naison
62b0de99f9 hotfix: typo (#293) 2024-07-08 21:42:51 +08:00
naison
295a7a709e feat: update krew index version to refs/tags/v2.2.13 (#292)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-07-05 23:11:33 +08:00
kubenetworks
8d400fd698 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-07-05 15:08:40 +00:00
naison
5f0fe6668a feat: cmd version use short commitid (#291) 2024-07-05 22:21:19 +08:00
naison
993be34b70 hotfix: delete from hosts while service is be deleted (#290) 2024-07-05 22:01:43 +08:00
naison
8093cb125a hotfix: fix list and watch pod/service to add route bug (#289) 2024-07-05 22:00:59 +08:00
naison
d3542b840a hotfix: fix log rotate (#288) 2024-07-05 22:00:20 +08:00
naison
d2faffc2c7 hotfix: fix log rotate (#287) 2024-07-05 21:59:33 +08:00
naison
d2648aabed hotfix: fix log rotate (#286) 2024-07-05 21:58:09 +08:00
naison
0e87705e5e hotfix: add timeout to ssh dial (#285) 2024-07-05 21:57:35 +08:00
naison
2d947f965f docs: update README.md (#284) 2024-07-03 23:24:24 +08:00
naison
35ef5a8c88 docs: add use brew to install kubevpn (#282) 2024-06-30 14:53:02 +08:00
naison
ce750d9c74 feat: update krew index version to refs/tags/v2.2.12 (#281)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-06-29 23:38:45 +08:00
kubenetworks
207445640e Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-06-29 15:36:12 +00:00
naison
e9327ec572 fix: fix watch pod/svc resource version too old (#280) 2024-06-29 11:56:31 +08:00
naison
deb4ec98f5 fix: disconnect if operation connect has cancelled (#279) 2024-06-29 11:56:21 +08:00
naison
5cd7ef4a0a feat: update krew index version to refs/tags/v2.2.11 (#278)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-06-27 22:01:24 +08:00
naison
d6f833fc0b feat: only use tag judge daemon version (#277) 2024-06-26 22:11:05 +08:00
naison
faa6229aef feat: update krew index version to refs/tags/v2.2.11 (#276)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-06-24 10:11:53 +08:00
naison
98d88ac542 feat: makefile var use env (#275)
* feat: makefile var use env
2024-06-24 09:32:58 +08:00
naison
680e95fd7f feat: update krew index version to refs/tags/v2.2.11 (#273)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-06-22 11:07:38 +08:00
naison
4aeee5f8d8 feat: discard syncthing log (#272) 2024-06-22 10:33:37 +08:00
naison
28d2e78d04 feat: update krew index version to refs/tags/v2.2.11 (#271)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-06-21 22:18:09 +08:00
kubenetworks
d8e0cbcc3d Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-06-21 14:13:54 +00:00
naison
ed4c6bbe2f feat: add syncthing for clone mode (#270)
* feat: add syncthing for clone mode

---------

Co-authored-by: wencaiwulue <895703375@qq.com>
2024-06-21 21:27:20 +08:00
naison
a45688115c feat: push image to ghcr (#269) 2024-06-14 21:17:50 +08:00
naison
35f0568b09 doc: add contribution to readme (#267) 2024-05-31 11:35:14 +08:00
naison
2ec20f7d1d refactor: upgrade (#266) 2024-05-24 10:54:12 +08:00
naison
a26abab8ce refactor: command get (#265) 2024-05-24 10:53:58 +08:00
naison
9be029e65e feat: update krew index version to refs/tags/v2.2.10 (#262)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-21 19:58:17 +08:00
naison
6fed288e67 chore: add label to get cidr pod spec (#261)
* chore: add label to get cidr pod spec

* chore: add label selector
2024-05-21 19:14:08 +08:00
naison
80e3aa154c chore: add label to get cidr pod spec (#260) 2024-05-21 18:51:54 +08:00
naison
38b9ad1991 hotfix: fix get cidr npe (#259) 2024-05-21 18:40:55 +08:00
naison
eaacf3954f feat: update krew index version to refs/tags/v2.2.10 (#258)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-21 14:47:24 +08:00
kubenetworks
12a12bcda7 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-05-21 06:46:20 +00:00
naison
28f6d54398 hotfix: remove PriorityClassName from deploy spec (#257) 2024-05-21 14:15:59 +08:00
naison
a23b197554 feat: update krew index version to refs/tags/v2.2.9 (#254)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-17 09:36:20 +08:00
naison
a0ca862d59 chore: update alias config example (#253) 2024-05-17 08:58:50 +08:00
naison
7dd762b853 feat: update krew index version to refs/tags/v2.2.9 (#252)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-16 14:37:34 +08:00
naison
78762cd9e5 hotfix: fix clone mode use jumped kubeconfig (#251) 2024-05-16 10:53:58 +08:00
kubenetworks
e58a9bf69e Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-05-14 11:50:55 +00:00
naison
a10b1b2526 feat: update krew index version to refs/tags/v2.2.9 (#250)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-14 19:50:23 +08:00
naison
331423c308 feat: not set ipv6 if ipv6 is not enable on linux (#248)
* feat: not set ipv6 if ipv6 is not enable on linux
2024-05-14 14:17:34 +08:00
naison
e5c1ea4b9b hotfix: fix set ipv4 on bsd (#249) 2024-05-14 13:02:26 +08:00
naison
cc032c4a6d feat: write pprof to file when daemon quit (#247) 2024-05-14 11:19:58 +08:00
naison
984ab2ce89 hotfix: cancel ctx (#246) 2024-05-14 10:31:08 +08:00
naison
3e51bf0f4d hotfix: close chan (#245) 2024-05-13 19:58:56 +08:00
naison
e7f00f5899 hotfix: cleanup in time when connect lite mode (#243) 2024-05-13 10:14:54 +08:00
naison
70d5723e97 refactor: refactor daemon process (#242)
* refactor: refactor daemon process

* hotfix: add fsnotify to watch pid file
2024-05-10 21:39:14 +08:00
naison
5da018db2a feat: update krew index version to refs/tags/v2.2.8 (#241)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-07 19:35:00 +08:00
naison
a0137ad485 hotfix: fix alias (#240) 2024-05-07 19:02:39 +08:00
naison
37552d3db9 feat: update krew index version to refs/tags/v2.2.8 (#239)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-05-03 23:51:27 +08:00
kubenetworks
5ac8eac923 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-05-03 15:50:14 +00:00
naison
d2d411a1cb feat: support ssh jump inline (#238)
* feat: support ssh jump inline

* chore: add more comment
2024-05-03 22:28:25 +08:00
naison
d16bdf8fea hotfix: use flag gssapi as default value (#237) 2024-05-01 09:53:00 +08:00
naison
ca18dab08f refactor: refactor cmd status (#236)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-30 22:02:48 +08:00
naison
706afb348d feat: update krew index version to refs/tags/v2.2.7 (#235)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-04-27 20:47:48 +08:00
kubenetworks
def6c7dfdd Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-04-27 12:11:36 +00:00
naison
e64dd428ab chore: ut use macos12 not latest (#234) 2024-04-27 19:39:21 +08:00
naison
9df4efb98b refactor: refactor cmd alias status and disconnect (#233)
* refactor: refactor cmd alias status and disconnect

---------

Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-27 18:22:34 +08:00
naison
6f6d338656 hotfix: fix not add route bug (#228) 2024-04-27 09:58:54 +08:00
naison
f93b06ea1c feat: cmd alias config file support special (#232) 2024-04-27 09:58:38 +08:00
naison
ada4b51035 hotfix: fix proxy with service mesh failed on latest minikube (#231) 2024-04-26 16:11:16 +08:00
naison
679d097e83 hotfix: add cmd status missing field netif (#230) 2024-04-25 11:44:04 +08:00
naison
c7b437c5d8 hotfix: fix cmd status not correct when tun is gone (#229) 2024-04-25 10:48:46 +08:00
naison
43dad39cca chore: run ut coverage on linux (#227) 2024-04-24 18:54:35 +08:00
naison
d428ee42bc hotfix: add portmap to envoy rule (#224) 2024-04-24 17:32:28 +08:00
naison
0e569fe1a4 hotfix: fix dns method genereateHostsEntry NPE (#226) 2024-04-24 17:32:18 +08:00
naison
fe7be90d0b hotfix: fix tun device no buffer space available (#225) 2024-04-24 17:32:04 +08:00
naison
bacc8cdc26 refactor: remove foreground in daemon (#223) 2024-04-20 20:54:33 +08:00
naison
9c62504489 feat: add command alias (#222)
* feat: add command alias

* feat: kube config path support homedir ~
2024-04-20 19:42:20 +08:00
naison
6060bd8120 feat: update krew index version to refs/tags/v2.2.6 (#221)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-04-16 13:44:43 +08:00
kubenetworks
2cd4de52f4 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-04-16 05:44:32 +00:00
naison
03ac484069 hotfix: downgrade tun driver version (#220)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-16 13:08:13 +08:00
naison
c7b4499503 feat: update krew index version to refs/tags/v2.2.5 (#219)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-04-14 16:54:13 +08:00
kubenetworks
9a7466479b Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-04-14 08:46:14 +00:00
naison
31d7e4debb refactor: refactor dns (#218)
* refactor: refactor dns

* refactor: optimize forward dns server

* refactor: add short domain test

* refactor: fix remove nameserver from resolver bug

---------

Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-13 16:39:26 +08:00
Pengfei Jiang
52f1d38e56 fix(connect): fix connect foreground exit failed (#214)
* fix(connect): fix connect foreground exit failed

* fix(*): fix lint

* fix: disconnect by kubeconfig instead of id

---------

Co-authored-by: 江鹏飞 <jiangpengfei.jiangpf@bytedance.com>
2024-04-12 23:47:14 +08:00
naison
acd4de313f fix: fix dev mode connect-mode is container -p not works (#217)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-12 21:45:50 +08:00
naison
8dbb80be7c hotfix: fix tun bug (#216)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-12 21:45:31 +08:00
naison
45491f185d hotfix: fix ping bug (#213)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-06 13:16:13 +08:00
naison
4eeecd5255 refactor: refactor get cidr logic (#211)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-05 11:03:52 +08:00
naison
87166494c0 refactor: update go mod library (#210)
refactor: update go mod library and refactor dev logic

Co-authored-by: wencaiwulue <895703375@qq.com>
2024-04-04 12:04:02 +08:00
naison
91b3a2fbdf feat: update krew index version to refs/tags/v2.2.4 (#206)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-04-02 14:04:56 +08:00
kubenetworks
b7615f57c3 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-04-02 05:15:00 +00:00
naison
e5438b297a fix: fix proxy mode bug (#205) 2024-04-02 12:43:40 +08:00
naison
d3aeae7573 hotfix: fix flag context not works bug (#204) 2024-04-01 11:44:59 +08:00
naison
aacdc8a6d0 feat: update gvisor with tag go and go with 1.22 (#202) 2024-03-31 22:42:31 +08:00
naison
fadfd00927 hotfix: fix cpu usage high cause by in loop to call <-time.Tick(xxx) (#201)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-31 11:05:34 +08:00
naison
600e35b8d7 refoctor: ssh logic (#194)
* feat: optimize ssh
2024-03-08 19:16:29 +08:00
naison
f3d1c99a04 docs: add codecov badge (#193) 2024-03-05 11:41:07 +08:00
naison
18a5569054 feat: add ut coverage (#192) 2024-03-05 10:02:31 +08:00
naison
1baa1de13f feat: update krew index version to refs/tags/v2.2.3 (#191)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-03-04 13:10:30 +08:00
naison
dcda747d0e fix: fix portmap bug (#190) 2024-03-04 12:38:05 +08:00
naison
2fd6427242 feat: update krew index version to refs/tags/v2.2.3 (#189)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-03-04 00:31:36 +08:00
naison
dc270ca846 fix: fix set hosts bug (#188)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-03 23:58:21 +08:00
naison
ab0cd80b39 feat: update krew index version to refs/tags/v2.2.3 (#187)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-03-03 19:55:31 +08:00
kubenetworks
e920133c88 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-03-03 11:52:38 +00:00
naison
0d64dc7b10 refactor: optimize dns code (#186)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-03 17:31:52 +08:00
naison
96845ba37a feat: disconnect-by-extra-route-dependency (#185)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-03 15:22:26 +08:00
naison
0730cb12b7 refactor: move ssh jump to util (#184)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-03 11:49:44 +08:00
naison
e232bf902e refactor: optimize ssh and set dns server logic (#183)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-03 00:57:47 +08:00
naison
1bc269d901 fix: fix proxy mode add portmap options (#182)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-03-03 00:53:25 +08:00
naison
a8826b3334 feat: add extra node ip to route table (#179)
* feat: add extra node ip to route table
2024-02-27 18:00:52 +08:00
naison
7c560df82b feat: last connect will first disconnect (#180) 2024-02-27 11:52:47 +08:00
Anton Patsev
939cc8547f Add missing commas, correction of spelling errors (#178) 2024-02-26 00:11:54 +08:00
naison
fed7108eec refactor: move reset command to daemon (#175)
* feat: move cmd reset to daemon

* feat: move cmd reset to daemon

---------

Co-authored-by: wencaiwulue <895703375@qq.com>
2024-02-25 15:49:31 +08:00
naison
2fdfc1d88d feat: proxy mode add portmap option (#176)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-02-23 21:17:24 +08:00
naison
64cd7709e8 fix: fix helm chart (#177)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-02-23 21:16:52 +08:00
naison
5773b69367 fix: close udp conn if timeout (#173) 2024-02-19 22:09:46 +08:00
naison
c689f47664 fix: fix remove pid (#172) 2024-02-18 19:28:46 +08:00
naison
1f32a129b6 feat: update krew index version to refs/tags/v2.2.2 (#171)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-02-17 20:11:07 +08:00
naison
01e3456ad3 fix: ssh portmap redo ssh dial (#170) 2024-02-17 19:25:35 +08:00
naison
46fcf5521f feat: update krew index version to refs/tags/v2.2.2 (#169)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-02-15 21:46:04 +08:00
kubenetworks
26f53209c6 Update charts/index.yaml
Signed-off-by: kubenetworks <kubenetworks@users.noreply.github.com>
2024-02-15 13:35:35 +00:00
fengcaiwen
454f67b6c4 feat: github action add release helm chart 2024-02-15 20:57:41 +08:00
naison
bd5c3c4cf6 feat: empty helm charts image tag (#150) 2024-02-15 13:28:28 +08:00
naison
991a840db2 feat: add manifest helm chart (#145)
* feat: add manifest helm chart

* fix: typo

* feat: helm chart

* feat: add github action to release helm chart

---------

Co-authored-by: wencaiwulue <895703375@qq.com>
2024-02-15 12:44:17 +08:00
naison
3ad6127132 feat: optimize code (#149)
Co-authored-by: wencaiwulue <895703375@qq.com>
2024-02-15 11:38:14 +08:00
naison
14e91d5110 feat: update unsafe pkg of go mod (#148) 2024-02-07 21:03:38 +08:00
naison
4abc5f004a fix: fix some bug and optimize ssh logic (#147) 2024-02-07 20:36:10 +08:00
naison
59abb16136 fix: fix proxy mode option image not work bug (#146) 2024-02-06 22:07:44 +08:00
naison
6a232473cd feat: auto upgrade daemon (#144) 2024-02-02 22:24:23 +08:00
naison
878a8190e3 chore: update readme godoc (#143) 2024-02-01 23:03:02 +08:00
naison
d0978aa5b7 fix: fix delete socks file and pid file not work bug (#142) 2024-02-01 22:47:03 +08:00
naison
073c249e96 fix: fix rotate log bug (#141) 2024-02-01 22:22:26 +08:00
naison
78c8afb456 fix: fix ssh hang up issue (#140) 2024-01-30 21:44:17 +08:00
naison
0384de250a fix: add \n before append host entry (#139) 2024-01-29 23:08:50 +08:00
naison
9be04cc149 feat: dhcp server use grpc instead of http (#138) 2024-01-28 14:42:37 +08:00
naison
f9ef4c8dad fix: add lock to handle webhook event 2024-01-27 16:33:02 +08:00
naison
c09ac8f536 fix: add lock in case of rent same ip (#136)
Co-authored-by: 冯才文 <fengcaiwen@buns-macbook-pro.local>
2024-01-27 00:34:18 +08:00
3deep5me
14731fe8e8 Add more documentation about connect mode (#134)
* add disclaimer to short domain resolve

* updated introduction

* Added content menu for Readme

* changed picture for connect mode to draw.io

* removed wireguard from picture
2024-01-26 00:47:56 +08:00
naison
dc33331a8c feat: add reference doc (#131) 2024-01-18 10:24:52 +08:00
naison
879bdbc03d feat: update krew index version to refs/tags/v2.2.1 (#129)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-01-17 19:57:59 +08:00
naison
8eeb420245 feat: set IPv6 addr only if IPv6 is enabled on Windows (#128) 2024-01-17 19:11:29 +08:00
naison
847c2c8cc1 feat: update go mod to v2 (#127)
* feat: update go mod to v2

* feat: typo
2024-01-14 18:00:12 +08:00
naison
988c2e7fdc feat: update krew index version to refs/tags/v2.2.1 (#126)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-01-12 11:22:45 +08:00
naison
8c55d39af2 feat: set envoy log dynamic (#125)
* feat: set envoy log level dynamic

* feat: set log level
2024-01-12 10:47:49 +08:00
naison
e2cb639c6e feat: set envoy log level dynamic (#124) 2024-01-12 10:29:43 +08:00
naison
f9a67a2773 feat: update krew index version to refs/tags/v2.2.1 (#122)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-01-11 21:16:12 +08:00
naison
cbf3cdff42 fix: add service clusterIP (#121) 2024-01-11 20:43:42 +08:00
naison
d35656f3df feat: update krew index version to refs/tags/v2.2.1 (#118)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-01-10 21:00:49 +08:00
naison
9f97a9202d feat: set dns searchList by LUID not powershell.exe (#117) 2024-01-10 20:16:50 +08:00
naison
ae2b97a4b4 feat: update krew index version to refs/tags/v2.2.1 (#115)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-01-10 12:38:12 +08:00
fengcaiwen
156ee998cd feat: replace envoy config tunIP if header and uid is same 2024-01-10 12:05:32 +08:00
naison
b2a6e602e6 feat: update krew index version to refs/tags/v2.2.1 (#113)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2024-01-09 16:36:48 +08:00
fengcaiwen
8650e4ecf9 hotfix: fix too many portforward and too many watch service 2024-01-09 16:01:43 +08:00
naison
4a2abc24da chore: update README (#111)
* chore: update README

* chore: rename org name
2024-01-01 18:01:54 +08:00
naison
a66fbb1637 feat: upgrade client-go version to v0.29.0 (#109)
* feat: upgrade client-go version to v0.29.0

* feat: upgrade coredns version

* chore: update README.md
2024-01-01 16:45:54 +08:00
naison
c3c6864b47 fix: remove svc from hosts if svc deleted (#107) 2023-12-29 23:07:07 +08:00
naison
80ffd2f468 feat: update krew index version to refs/tags/v2.2.0 (#106)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2023-12-18 20:28:39 +08:00
naison
0ad6b103cb fix: add hosts only if not exists 2023-12-18 11:53:35 +00:00
fengcaiwen
d9977a5c11 fix: setup docker 2023-12-17 09:59:24 +08:00
naison
6fbae091ec feat: update krew index version to refs/tags/v2.2.0 (#105)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2023-12-16 23:57:01 +08:00
fengcaiwen
8505c26830 fix: close file 2023-12-16 23:27:58 +08:00
fengcaiwen
7c53cbc79b fix: download bug 2023-12-16 23:21:55 +08:00
fengcaiwen
c0da61cd4b fix: fix hosts bug 2023-12-16 22:52:49 +08:00
naison
1644201978 feat: optimize readme 2023-12-11 06:35:25 +00:00
naison
91ee5be981 feat: update krew index version to refs/tags/v2.1.3 (#104)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2023-12-10 19:36:46 +08:00
fengcaiwen
74bb3d3746 feat: update README.md 2023-12-10 18:54:00 +08:00
naison
51bb3b8700 fix: fix linux /etc/resolv.conf not restore bug (#103)
* fix: fix linux /etc/resolv.conf not restore bug

* fix: fix linux /etc/resolv.conf not restore bug
2023-12-10 18:53:07 +08:00
naison
c18b56eb2a fix: device or resource busy (#102) 2023-12-10 17:52:41 +08:00
naison
de050c2944 feat: resize ssh terminal (#101) 2023-12-01 22:49:21 +08:00
naison
49876dee05 feat: update krew index version to refs/tags/v2.1.2 (#100)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2023-11-28 21:47:15 +08:00
naison
abf36b87a6 fix: fix ssh bug (#99) 2023-11-28 20:21:11 +08:00
naison
5cc64d17c2 feat: update krew index version to refs/tags/v2.1.2 (#98)
Co-authored-by: wencaiwulue <wencaiwulue@users.noreply.github.com>
2023-11-26 18:13:04 +08:00
naison
c80f610fc1 feat: ssh support auth gssapi (#97)
* feat: support ssh auth GSSAPI

* feat: support ssh auth GSSAPI
2023-11-26 17:21:12 +08:00
naison
1a9593f140 feat: optimize code (#96)
optimize code and fix testcase
2023-11-23 12:35:34 +08:00
fengcaiwen
0e0885afd5 feat: rorate log 2023-11-21 21:52:45 +08:00
Jari Maijenburg
9e0c0b2bf0 Moved pods watching to after traffic manager pod is created 2023-11-21 14:36:13 +08:00
wencaiwulue
99601693d3 feat: update krew index version to refs/tags/v2.1.1 2023-11-07 18:32:25 +08:00
fengcaiwen
361c47dc49 chore: update testcase 2023-11-07 17:35:13 +08:00
fengcaiwen
36d953141a feat: set port-forward retry sleep duration 2023-11-07 17:34:50 +08:00
fengcaiwen
59e9b9d09a hotfix: fix quit daemon not works bug 2023-11-07 17:33:55 +08:00
wencaiwulue
f760eddf17 feat: update krew index version to refs/tags/v2.1.1 2023-11-05 12:31:08 +08:00
fengcaiwen
c2a07a3d95 chore: update testcase 2023-11-05 10:48:08 +08:00
fengcaiwen
b87b9c91ee hotfix: fix ssh failed issue 2023-11-05 10:39:21 +08:00
Alex Kim
09d9f777b4 add some proxy test comments 2023-11-05 10:36:17 +08:00
Alex Kim
025e21a796 message: use kubeconfig with tunneled 2023-11-04 16:42:41 +08:00
Alex Kim
af9d9094e7 add TLSServerName 2023-11-04 16:42:41 +08:00
Alex Kim
cb1f4dc690 add error message if ip not found 2023-11-03 11:36:40 +08:00
Alex Kim
6f94342d54 fix parseAddrPort error 2023-11-03 11:36:40 +08:00
wencaiwulue
13cf86b77c feat: update krew index version to refs/tags/v2.1.0 2023-10-29 18:27:24 +08:00
fengcaiwen
fa49431752 feat: ssh add BannerCallback 2023-10-29 17:11:53 +08:00
fengcaiwen
487ec8e24d feat: install if remote ssh server not exist command kubevpn 2023-10-29 17:11:53 +08:00
fengcaiwen
b2458c2020 feat: add ssh to linux server 2023-10-29 17:11:53 +08:00
fengcaiwen
faf7c5eff3 feat: optimize dns logic 2023-10-28 18:15:19 +08:00
fengcaiwen
457fda89a0 feat: optimize code 2023-10-28 18:15:19 +08:00
fengcaiwen
2d44c9b00d feat: lite mode not add route diy cidr 2023-10-28 18:15:19 +08:00
fengcaiwen
126eca32f8 feat: add origin kubeconfig path for show status 2023-10-28 18:15:19 +08:00
fengcaiwen
b25849657d feat: add connect lite mode and optimize dns 2023-10-28 18:15:19 +08:00
fengcaiwen
d3640ec2d1 feat: multiple connect works well 2023-10-28 18:15:19 +08:00
fengcaiwen
1f4ea3ba87 feat: disconnect works well 2023-10-28 18:15:19 +08:00
fengcaiwen
fec1f72b22 feat: remove env EnvKubeVPNTransportEngine 2023-10-28 18:15:19 +08:00
fengcaiwen
4a10be295f feat: remove env EnvTunNameOrLUID 2023-10-28 18:15:19 +08:00
fengcaiwen
6a6c4e3257 feat: add vendor 2023-10-21 22:41:53 +08:00
wencaiwulue
1c637f45b5 feat: update krew index version to refs/tags/v2.0.1 2023-10-21 20:17:34 +08:00
fengcaiwen
4c616bda95 chore: try to fix testcase 2023-10-21 19:13:48 +08:00
fengcaiwen
7ef69b5f30 chore: add comment 2023-10-21 18:48:14 +08:00
guoguangwu
afb2e9b667 chore: remove refs to deprecated io/ioutil 2023-10-17 11:20:20 +08:00
fengcaiwen
4c0715e83c feat: multiple connect 2023-10-13 15:41:05 +08:00
wencaiwulue
6252c57b6f feat: update krew index version to refs/tags/v2.0.0 2023-10-02 16:10:43 +08:00
fengcaiwen
6ca33ca3eb feat: dev add arg length validate 2023-10-02 15:09:39 +08:00
fengcaiwen
f314031b5e chore: fix log format 2023-10-02 14:52:02 +08:00
wencaiwulue
8e2d67ec2d feat: update krew index version to refs/tags/v2.0.0 2023-10-02 14:35:09 +08:00
fengcaiwen
c37ae5cd0e chore: update log 2023-10-02 13:44:23 +08:00
fengcaiwen
5bcba29837 feat: update README.md 2023-10-02 13:44:23 +08:00
fengcaiwen
cf138d24b6 feat: update README.md 2023-10-02 13:44:23 +08:00
fengcaiwen
fb93cb5748 feat: auto-remove container 2023-10-02 13:44:23 +08:00
fengcaiwen
4d10bd4124 feat: typo 2023-10-02 13:44:23 +08:00
fengcaiwen
5c581eeec3 feat: show less log 2023-10-02 13:44:23 +08:00
fengcaiwen
1a7a4e20d4 feat: fix bug 2023-10-02 13:44:23 +08:00
fengcaiwen
31369a19d6 feat: add more description 2023-10-02 13:44:23 +08:00
fengcaiwen
a0f7fd0f06 feat: use context 2023-10-02 13:44:23 +08:00
fengcaiwen
223e41eb30 feat: ssh add heartbeat 2023-10-02 13:44:23 +08:00
fengcaiwen
075c736279 feat: add command ssh 2023-10-02 13:44:23 +08:00
fengcaiwen
a340ae3d8d feat: config works should well 2023-10-02 13:44:23 +08:00
fengcaiwen
1af3d0ba0f feat: use default ssh key 2023-10-02 13:44:23 +08:00
fengcaiwen
bf3aa66d22 feat: get works not well 2023-10-02 13:44:23 +08:00
fengcaiwen
4301e222a8 feat: clone works well 2023-10-02 13:44:23 +08:00
fengcaiwen
c3df4e3ffa feat: upgrade works on macOS and needs to test on Windows 2023-10-02 13:44:23 +08:00
fengcaiwen
d0436c6472 feat: dev mode auto port map 2023-10-02 13:44:23 +08:00
fengcaiwen
dff44ed041 feat: dev options use kubectl style 2023-10-02 13:44:23 +08:00
fengcaiwen
e801209349 feat: dev with ssh works well 2023-10-02 13:44:23 +08:00
fengcaiwen
6b1ea53cd6 feat: dev with ssh works well 2023-10-02 13:44:23 +08:00
fengcaiwen
ab6b9ae2a2 feat: log more info 2023-10-02 13:44:23 +08:00
fengcaiwen
76f1b74076 feat: log more info 2023-10-02 13:44:23 +08:00
fengcaiwen
5c818af126 feat: optimize log 2023-10-02 13:44:23 +08:00
fengcaiwen
0e24b22bda feat: clone works well 2023-10-02 13:44:23 +08:00
fengcaiwen
f91507102e feat: clone works well 2023-10-02 13:44:23 +08:00
fengcaiwen
49e8a14118 feat: daemon works well on Windows 2023-10-02 13:44:23 +08:00
fengcaiwen
977d902b8b feat: daemon works well on Windows 2023-10-02 13:44:23 +08:00
fengcaiwen
5cb198e241 feat: daemon works well on windows 2023-10-02 13:44:23 +08:00
fengcaiwen
a1484556b9 feat: wip 2023-10-02 13:44:23 +08:00
fengcaiwen
53b90fef76 feat: daemon not works well on Windows 2023-10-02 13:44:23 +08:00
fengcaiwen
9641e29d6e feat: needs to test serve 2023-10-02 13:44:23 +08:00
fengcaiwen
baedcb114c feat: cleanup works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
e30e59fc50 feat: logs works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
da572aafb4 feat: logs works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
cacb65efb9 feat: restore patch works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
b9798e66f0 feat: restore patch not work, others is ok 2023-10-02 13:44:23 +08:00
fengcaiwen
743bbaa370 feat: proxy works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
bcdd2cfa6b feat: ssh works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
87132cec22 feat: works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
48417b0e49 feat: works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
8df0b0c5cf feat: works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
e945559f8e feat: optimize code 2023-10-02 13:44:23 +08:00
fengcaiwen
8e017ea64d feat: optimize code 2023-10-02 13:44:23 +08:00
fengcaiwen
29f5c191a5 feat: optimize code 2023-10-02 13:44:23 +08:00
fengcaiwen
a7ca7853f5 feat: optimize code 2023-10-02 13:44:23 +08:00
fengcaiwen
8b93812e01 feat: works fine 2023-10-02 13:44:23 +08:00
fengcaiwen
8e4dc9006d feat: optimize 2023-10-02 13:44:23 +08:00
fengcaiwen
9b1c8dd97d feat: optimize cleanup logic 2023-10-02 13:44:23 +08:00
fengcaiwen
8eab75f300 feat: add daemon and connect is ok 2023-10-02 13:44:23 +08:00
naison
dc2936078b chore 2023-09-02 03:54:41 +00:00
wencaiwulue
473ac16e57 feat: update krew index version to refs/tags/v1.2.0 2023-09-02 11:49:23 +08:00
fengcaiwen
945785af95 feat: optimize release.yml 2023-09-02 09:08:11 +08:00
fengcaiwen
82e3c7af33 hotfix: fix setup docker 2023-09-02 08:45:55 +08:00
fengcaiwen
c1d1bacef0 feat: remove container only if auto-remove is true 2023-09-02 08:42:13 +08:00
fengcaiwen
7ee9925d5e feat: upgrade if commit id not match 2023-08-24 11:13:04 +08:00
wencaiwulue
a3d131d42f feat: update krew index version to refs/tags/v1.1.36 2023-08-23 23:59:58 +08:00
fengcaiwen
453afc5d49 fix: fix no avaliable buffer bug 2023-08-23 22:58:24 +08:00
wencaiwulue
172033a227 feat: update krew index version to refs/tags/v1.1.36 2023-08-20 17:10:55 +08:00
fengcaiwen
09b02bc2d7 feat: remove gvisor mode temporally 2023-08-20 16:10:20 +08:00
fengcaiwen
92bf36bd3d feat: complete gvisor 2023-08-20 15:17:29 +08:00
fengcaiwen
d94db893db feat: update github action go version 2023-08-20 15:17:29 +08:00
fengcaiwen
b0e2e0e2b9 feat: single connection broken will not redo port-forward 2023-08-20 15:17:29 +08:00
fengcaiwen
ff2fcf939f feat: complete gvisor 2023-08-20 15:17:29 +08:00
fengcaiwen
30bf4838c2 feat: fix route conn bugs 2023-08-20 15:17:29 +08:00
fengcaiwen
c07879e78a feat: use gvisor to optimize udp performance 2023-08-20 15:17:29 +08:00
fengcaiwen
bf47c6f4e1 feat: use gvisor to optimize performance 2023-08-20 15:17:29 +08:00
fengcaiwen
27482158e7 hotfix: github action setup docker on macOS failed issue 2023-08-19 23:40:26 +08:00
fengcaiwen
3265d26b27 feat: optimize dns query while special parameter extra-domain 2023-08-19 17:56:58 +08:00
wencaiwulue
a3651cf370 feat: update krew index version to refs/tags/v1.1.35 2023-08-16 23:11:07 +08:00
naison
68ff79ca98 hotfix: rollback mtu 2023-08-16 10:54:03 +00:00
wencaiwulue
414ac0e79d feat: update krew index version to refs/tags/v1.1.35 2023-08-16 10:58:38 +08:00
naison
22d34fe362 hotfix(proxy): fix proxy without header not work bug 2023-08-16 02:04:34 +00:00
wencaiwulue
37c901c633 feat: update dockerfile 2023-08-08 22:28:38 +08:00
fengcaiwen
6fb80496e6 feat: nat use rlock while route 2023-08-06 12:02:44 +08:00
fengcaiwen
5f08427105 feat: optimize code 2023-08-04 17:11:15 +08:00
fengcaiwen
97042d6ed0 fix: judge list pod permission to add route 2023-08-02 10:45:45 +08:00
fengcaiwen
3c854cb1c7 fix: add heartbeats 2023-08-01 15:47:57 +08:00
wencaiwulue
7555311599 chore(doc): update readme 2023-07-30 15:21:15 +08:00
wencaiwulue
f550cc9a05 feat: update krew index version to refs/tags/v1.1.35 2023-07-29 20:20:23 +08:00
fengcaiwen
ca67d1144a fix: fix connect-mode is container and no permission to set ipv6 address 2023-07-29 19:02:12 +08:00
wencaiwulue
9f6304d4f8 feat: update krew index version to refs/tags/v1.1.35 2023-07-28 16:49:17 +08:00
fengcaiwen
f934c33952 fix: fix bug 2023-07-28 16:09:21 +08:00
fengcaiwen
913f8648e3 feat: enable build image 2023-07-26 13:07:19 +08:00
fengcaiwen
44e4dcc678 feat: adjust resource 2023-07-26 13:04:23 +08:00
fengcaiwen
3b3165c88b fix: keep route ip 2023-07-26 12:59:41 +08:00
fengcaiwen
6511d58dc2 perf: use chan to communicate between tcpserver and tun 2023-07-26 12:50:32 +08:00
fengcaiwen
2ba7b2027f perf: use chan to communicate between tcpserver and tun 2023-07-26 12:50:32 +08:00
fengcaiwen
d87363d2cd perf: use chan to communicate between tcpserver and tun 2023-07-26 12:50:32 +08:00
fengcaiwen
fdf75b0f0f fix: keep router ip 2023-07-22 18:12:31 +08:00
fengcaiwen
dc07514a1c chore: update comment 2023-07-18 15:20:53 +08:00
fengcaiwen
b90f9c3674 fix: update krew index repo name 2023-07-17 17:37:00 +08:00
wencaiwulue
e63229afde feat: update krew index version to refs/tags/v1.1.34 2023-07-17 17:34:27 +08:00
fengcaiwen
b0ed57794f fix: fix cidr-domain not works bug 2023-07-17 16:25:11 +08:00
wencaiwulue
6a4c787006 feat: update krew index version to refs/tags/v1.1.34 2023-07-15 19:14:27 +08:00
fengcaiwen
32886a5a5d Merge remote-tracking branch 'origin/master' 2023-07-15 18:35:45 +08:00
fengcaiwen
67786f82fd fix: re-rent ip if pod restart 2023-07-15 18:35:26 +08:00
fengcaiwen
caac77c7e5 fix: ping each other on Windows 2023-07-15 18:35:07 +08:00
fengcaiwen
0872c39b63 fix: auto determine protocol 2023-07-15 18:34:46 +08:00
wencaiwulue
c5cdafd389 feat: update krew index version to refs/tags/v1.1.34 2023-07-13 19:56:30 +08:00
Weijie
c65d4be05e fix typo 2023-07-13 15:52:22 +08:00
fengcaiwen
cc8eb9d939 feat: support client-go multiple auth 2023-06-26 19:24:48 +08:00
naison
2a7e522861 Update README_ZH.md 2023-06-20 17:47:43 +08:00
naison
e85aed59ec Update README.md 2023-06-20 17:47:28 +08:00
fengcaiwen
964ee73eb3 feat: enable test build on windows 2023-06-15 14:29:57 +08:00
fengcaiwen
75e2929f4a feat: migrate to organization 2023-06-09 17:57:36 +08:00
fengcaiwen
fd061499c1 feat: update README.md 2023-06-08 17:30:16 +08:00
fengcaiwen
45c08641d4 Merge remote-tracking branch 'origin/master' 2023-06-02 21:37:48 +08:00
fengcaiwen
bb29be937e feat: update README.md 2023-06-02 21:37:24 +08:00
wencaiwulue
57ff87bee8 feat: update krew index version to refs/tags/v1.1.33 2023-06-01 11:55:18 +08:00
naison
f3568f5b13 fix: fix grpc origin cluster protocol error 2023-06-01 02:48:21 +00:00
Pengfei Jiang
5fe1bf3910 Merge pull request #42 from joyme123/feat-localdns
feat(dns): support localdns to forward dns query
2023-05-31 17:53:25 +08:00
江鹏飞
1ab038d153 chore(build): build for mac and windows 2023-05-31 17:41:12 +08:00
江鹏飞
75c1b81786 feat(dns): support localdns to forward dns query 2023-05-31 17:31:16 +08:00
naison
19bcb290bb feat: update test.yml 2023-05-31 07:17:33 +00:00
naison
eff162f22d feat: update test.yaml 2023-05-31 06:05:15 +00:00
fengcaiwen
bd17575b87 feat: ssh support use remote kubeconfig 2023-05-27 10:20:04 +08:00
wencaiwulue
5a637b5efe feat: update krew index version to refs/tags/v1.1.32 2023-05-20 13:11:08 +08:00
fengcaiwen
b8e183ca82 feat: support more docker options 2023-05-18 14:48:00 +08:00
naison
f20bf21e6b Revert "feat: update krew index version to refs/tags/v1.1.32"
This reverts commit c21088ee1e.
2023-05-18 14:09:30 +08:00
wencaiwulue
c21088ee1e feat: update krew index version to refs/tags/v1.1.32 2023-05-17 21:36:08 +08:00
wencaiwulue
b05a565304 feat: use errgroup to run server 2023-05-17 20:53:53 +08:00
fengcaiwen
f9c0a674be feat: support more docker options 2023-05-17 14:27:52 +08:00
wencaiwulue
f77a0170d7 Merge remote-tracking branch 'origin/master' 2023-05-07 22:48:31 +08:00
fengcaiwen
41049d46f7 feat: use errgroup to run server 2023-05-06 12:38:08 +08:00
wencaiwulue
1824da1760 feat: update krew index version to refs/tags/v1.1.31 2023-05-05 10:23:29 +08:00
wencaiwulue
c26f9495e0 fix: add route table except api server address 2023-05-04 18:32:35 +08:00
fengcaiwen
1ff2df43c2 fix: fix platform not works bug 2023-04-28 17:33:07 +08:00
wencaiwulue
fbc156fc16 feat: update krew index version to refs/tags/v1.1.30 2023-04-13 00:37:48 +08:00
wencaiwulue
25dc7c5786 feat: fix npe 2023-04-12 20:38:25 +08:00
fengcaiwen
f1fe93ab25 feat: update resource quota 2023-04-10 20:58:46 +08:00
fengcaiwen
8f6c987778 fix: fix bug 2023-04-10 17:57:05 +08:00
fengcaiwen
f2de9a8b1d feat: dns server add rate limit 2023-04-10 14:56:31 +08:00
fengcaiwen
71ed7e6bdb feat: support transfer image to remote 2023-04-10 12:51:26 +08:00
fengcaiwen
b2a6596405 feat: set cleanup timeout to 5 seconds 2023-04-09 17:07:54 +08:00
fengcaiwen
2b97dd3038 feat: ssh keyfile support "~" and support include syntax 2023-04-08 12:48:36 +08:00
fengcaiwen
f7c0d3c0ce feat: extra-domain support ipv6 fix ssh-jump not use --kubeconfig options bug 2023-04-08 12:05:24 +08:00
fengcaiwen
1fed5cc266 feat: pprof use random port 2023-04-03 21:24:57 +08:00
wencaiwulue
2227a82125 feat: support ipv6 2023-04-02 22:11:43 +08:00
wencaiwulue
16eb86290f feat: update krew index version to refs/tags/v1.1.29 2023-03-27 10:16:17 +08:00
wencaiwulue
aafee9ca5d feat: optimize code 2023-03-27 09:34:44 +08:00
fengcaiwen
4d01468e1d feat: use netlink 2023-03-24 14:59:23 +08:00
fengcaiwen
7435d2c75b feat: set image 2023-03-24 11:52:11 +08:00
wencaiwulue
6fccccc3bf feat: header match ignore case 2023-03-23 23:59:49 +08:00
wencaiwulue
5c9928ad9a feat: auto update image version 2023-03-23 23:59:19 +08:00
fengcaiwen
a323bae035 feat: delete deployment only reset 2023-03-23 14:22:23 +08:00
fengcaiwen
5ecebf2958 feat: remove docker network if container length is zero 2023-03-23 10:48:08 +08:00
wencaiwulue
100c60a90a feat: kill container with signal SIGTERM 2023-03-23 09:37:40 +08:00
fengcaiwen
593f42aeca feat: add mode connect-mode 2023-03-22 23:50:09 +08:00
wencaiwulue
2ccf5776a8 feat: not create network if already exist 2023-03-22 09:38:41 +08:00
wencaiwulue
2b41cfa11f Merge branch 'master' of github.com:wencaiwulue/kubevpn 2023-03-21 23:18:59 +08:00
wencaiwulue
3cef2861f0 feat: add tools conntrack 2023-03-21 23:15:16 +08:00
wencaiwulue
a9c7f8dcb0 feat: use created network to startup container 2023-03-21 23:14:47 +08:00
fengcaiwen
3f7a8f07ee feat: use one clientset 2023-03-21 11:41:55 +08:00
wencaiwulue
6bbc1c66d9 feat: update krew version 2023-03-21 09:17:02 +08:00
fengcaiwen
feabc95ee8 feat: add dlv for container-local 2023-03-20 22:29:15 +08:00
fengcaiwen
bde2ee42e0 feat: add options extra-domain 2023-03-20 19:43:42 +08:00
fengcaiwen
37dec0506f feat: use user root as container user 2023-03-20 19:25:07 +08:00
fengcaiwen
661032c012 feat: free tun library 2023-03-20 19:24:26 +08:00
fengcaiwen
d074bd0e62 fix: fix dev port-mapping not work 2023-03-20 19:24:03 +08:00
fengcaiwen
396bcdf11f feat: pull image use authconfig 2023-03-20 19:23:32 +08:00
fengcaiwen
cb10a537b3 feat: add timezone info 2023-03-20 19:22:45 +08:00
fengcaiwen
66cb70e1c2 feat: show options as prompt 2023-03-20 09:35:32 +08:00
fengcaiwen
68b43d1a73 feat: dns enable singleInFlight 2023-03-20 08:46:13 +08:00
fengcaiwen
c99f14bb8d feat: add cache for control-plane 2023-03-20 08:33:18 +08:00
fengcaiwen
b120dc4b0d feat: update krew version 2023-03-17 22:36:38 +08:00
fengcaiwen
fbae06a5ae feat: fix dind network bug 2023-03-17 21:48:46 +08:00
fengcaiwen
e2dd6e8f99 feat: call uninstall 2023-03-17 21:48:46 +08:00
fengcaiwen
5fe3560d93 feat: add heartbeats to each other 2023-03-17 21:48:46 +08:00
fengcaiwen
4a5c1374fb feat: optimize code 2023-03-17 21:48:46 +08:00
fengcaiwen
1970f30f9d feat: optimize code 2023-03-17 21:48:46 +08:00
fengcaiwen
a545f3a958 feat: use 32345 as pprof port 2023-03-17 21:48:46 +08:00
fengcaiwen
ac3c7c218f feat: use network instead of parent-container 2023-03-17 21:48:46 +08:00
wencaiwulue
321a63ab96 feat: disable update official krew index 2023-03-15 21:35:04 +08:00
fengcaiwen
4f4a545ecb feat: add options target-registry for duplicate mode 2023-03-15 21:17:29 +08:00
fengcaiwen
ad3faed1e6 feat: add option extra-cidr 2023-03-15 21:17:29 +08:00
fengcaiwen
198f8a0ced feat: update usage 2023-03-15 21:17:29 +08:00
fengcaiwen
7ea21f4aeb feat: set volume and env for duplicate mode 2023-03-15 21:17:29 +08:00
wencaiwulue
09528748b0 feat: optimize code 2023-03-15 21:17:29 +08:00
wencaiwulue
4f9d1f7db8 feat: add mode duplicate 2023-03-15 21:17:29 +08:00
wencaiwulue
42d5f3c8cf feat: set nameserver amount 2 2023-03-14 21:24:48 +08:00
wencaiwulue
c76ea03dfe feat: add command cp 2023-03-14 21:20:46 +08:00
wencaiwulue
30a82e25eb feat: pre-check oom in mode kubevpn dev 2023-03-14 09:38:14 +08:00
wencaiwulue
49229e70fe feat: heartbeats four times 2023-03-11 09:13:05 +08:00
fengcaiwen
caeaab9ba2 feat: split connect into connect and proxy 2023-03-10 20:49:22 +08:00
fengcaiwen
0d7f78f8ae feat: update comment 2023-03-10 18:41:52 +08:00
fengcaiwen
eb1eeb698e feat: call powershell and netsh add option no-window 2023-03-10 18:24:05 +08:00
fengcaiwen
75af5c2b14 feat: send heartbeats with gopacket 2023-03-10 17:35:59 +08:00
wencaiwulue
9a8e18f06f feat: fix build image 2023-03-09 21:39:29 +08:00
fengcaiwen
f7413ce0b9 feat: delete extension lib before exit 2023-03-09 18:02:12 +08:00
fengcaiwen
40de53fced feat: add FAQ 2023-03-09 16:00:43 +08:00
fengcaiwen
1f7678af66 feat: fix bugs 2023-03-09 12:06:11 +08:00
fengcaiwen
1b7794aa92 feat: optimize get cidr logic 2023-03-08 21:43:09 +08:00
fengcaiwen
9ab86c3baf feat: remove useless testcase 2023-03-08 09:22:23 +08:00
fengcaiwen
5d622c19d3 feat: support linux/arm64 2023-03-07 15:50:28 +08:00
fengcaiwen
a3d78da25c feat: use another way to startup container in dind 2023-03-06 21:28:02 +08:00
wencaiwulue
c1ef13ff87 feat: use json envoy config 2023-03-05 20:08:50 +08:00
wencaiwulue
226c7034d5 feat: update krew index version 2023-03-04 14:37:21 +08:00
fengcaiwen
8af9a9e6fa feat: support ssh ProxyJump 2023-03-04 13:51:04 +08:00
fengcaiwen
ac4c254cec feat: support ssh jumper 2023-03-03 18:12:59 +08:00
fengcaiwen
0ba0659ce3 feat: print version 2023-03-02 10:56:05 +08:00
wencaiwulue
4c9b1075ba feat: update krew index version 2023-03-01 23:36:34 +08:00
wencaiwulue
9469469689 feat: update envoy log level from debug to error 2023-03-01 22:40:14 +08:00
fengcaiwen
edac2dde39 feat: optimize 2023-02-28 19:52:28 +08:00
wencaiwulue
f2c663f7fb feat: optimize redo port-forward logic 2023-02-27 21:10:26 +08:00
wencaiwulue
f30a5dad19 feat: return err if setup dns failed 2023-02-27 08:52:39 +08:00
wencaiwulue
98358e0d2b feat: update krew registry version 2023-02-26 19:39:08 +08:00
wencaiwulue
5f814f6d02 feat: optimize performance 2023-02-26 18:25:50 +08:00
wencaiwulue
f490801f99 feat: update krew plugin version 2023-02-23 23:21:48 +08:00
fengcaiwen
c883398f37 feat: support dev docker in docker (dind) 2023-02-23 21:15:11 +08:00
fengcaiwen
c56e0c0baf feat: listen service add route 2023-02-23 09:06:38 +08:00
wencaiwulue
6326114bb1 feat: update krew plugin version 2023-02-22 23:37:22 +08:00
fengcaiwen
8b4b38d6c2 feat: use api to get and release ip 2023-02-22 17:11:13 +08:00
wencaiwulue
48c34d8512 feat: rent and release ip use api 2023-02-22 09:01:33 +08:00
wencaiwulue
1211a76700 feat: change sa if permission can't curd secrets and configmaps 2023-02-22 00:22:53 +08:00
wencaiwulue
faec23a854 feat: webhook not use klog 2023-02-21 23:02:36 +08:00
wencaiwulue
9c73aabcce feat: add cap for supporting dlv debug 2023-02-20 21:38:33 +08:00
wencaiwulue
85405c1a0f performance: change tun lib to wg 2023-02-19 12:14:47 +08:00
wencaiwulue
840695182c feat: fix testcase 2023-02-18 21:03:29 +08:00
wencaiwulue
9765b78ca4 feat: fix testcase 2023-02-18 20:31:33 +08:00
wencaiwulue
0e0533b307 feat: update custom krew index 2023-02-18 16:25:11 +08:00
wencaiwulue
bb124102e0 feat: update readme 2023-02-18 15:52:56 +08:00
wencaiwulue
acf7e67d59 feat: add default upgrade logic 2023-02-18 15:15:33 +08:00
wencaiwulue
35bf309fbd feat: add route dynamic 2023-02-17 21:36:39 +08:00
wencaiwulue
74194c3d76 feat: add hostname 2023-02-17 21:36:20 +08:00
wencaiwulue
f5084c04c6 feat: print port are mapping to host 2023-02-16 22:17:02 +08:00
wencaiwulue
c71cac977a feat: remove useless rollback 2023-02-16 22:04:02 +08:00
fengcaiwen
589f57afb0 feat: restore sa 2023-02-16 21:01:55 +08:00
fengcaiwen
674d4aeefe feat: add dev mode in docker container 2023-02-16 21:01:42 +08:00
wencaiwulue
cd41ebf2d8 feat: use download api to get current namespace 2023-02-14 22:15:19 +08:00
wencaiwulue
4b188ba6e9 feat: update krew plugin sha256 2023-02-12 16:55:45 +08:00
wencaiwulue
16702a5f3b feat: clean mesh envoy rule after exit and disable add route dynamic 2023-02-12 15:42:25 +08:00
wencaiwulue
46c2f01053 feat: add sa to mesh pod 2023-02-12 12:23:15 +08:00
wencaiwulue
826def9a4e feat: update customized krew index version from v1.1.16 --> v1.1.17 2023-02-11 21:04:49 +08:00
wencaiwulue
972cd55314 feat: optimize DNS experience on macOS 2023-02-11 20:33:05 +08:00
wencaiwulue
3c14dc4617 fix: update readme 2023-02-11 16:15:10 +08:00
wencaiwulue
84267a0491 fix: remove useless offset 2023-02-11 15:14:17 +08:00
wencaiwulue
b875c3ec5d feat: add current namespace service to hosts file 2023-02-11 14:48:43 +08:00
wencaiwulue
ec0e00e5cf feat: try to solve issue [Failed to set DNS configuration: Unit dbus-org.freedesktop.resolve1.service not found] 2023-02-10 23:04:41 +08:00
wencaiwulue
0c6b25ac1f feat: set namespace to mesh container 2023-02-10 21:27:35 +08:00
wencaiwulue
64e4070166 feat: set namespace to mesh container 2023-02-10 21:20:05 +08:00
fengcaiwen
93151f03f0 fix: ignore ping error 2023-02-10 12:03:51 +08:00
fengcaiwen
e9b99a1c18 fix: fix use cpu too high 2023-02-10 11:57:05 +08:00
fengcaiwen
db7286abec feat: feat: optimize code and remove detect conflict interface 2023-02-08 16:26:25 +08:00
wencaiwulue
2adfe3c525 feat: add custom krew index 2023-02-05 11:23:01 +08:00
wencaiwulue
7bc36352ff feat: fix upgrade unzip logic 2023-02-04 17:28:42 +08:00
wencaiwulue
ef980ad66e feat(release): zip release and add to krew 2023-02-04 12:21:21 +08:00
wencaiwulue
521dd43527 feat: ignore create webhook configuration permission deny 2023-02-04 12:09:42 +08:00
fengcaiwen
992f1e439d fix: final ways to keep get inbound tun ip 2023-02-02 11:05:53 +08:00
fengcaiwen
9cf8611144 feat: mesh mode support GRPC using envoy 2023-01-29 20:31:57 +08:00
fengcaiwen
68ec4440cb feat: upgrade envoy version from v1.21.1 --> v1.25.0 2023-01-29 20:30:50 +08:00
fengcaiwen
6c97c98bea feat: optimize code 2023-01-29 20:30:13 +08:00
wencaiwulue
b9e73eb105 feat: still try to get cidr from resources 2023-01-28 21:27:17 +08:00
wencaiwulue
24c9441f6c feat: still try to get cidr from resources 2023-01-28 20:55:55 +08:00
fengcaiwen
203e336341 feat: add pod listener to add route dynamically 2023-01-28 17:34:15 +08:00
wencaiwulue
c73f6c5ab2 feat: use factory to init clientset instead of use in cluster config 2023-01-27 11:10:26 +08:00
wencaiwulue
f128f5d58e feat: only retry to update ref-count on conflict 2023-01-26 21:57:15 +08:00
wencaiwulue
95f81df658 feat: remove useless code 2023-01-20 21:58:02 +08:00
wencaiwulue
eab3fde83a feat: upgrade dockerfile go version to 1.19 2023-01-20 11:07:14 +08:00
wencaiwulue
1ae99e42f5 feat: optimize chinese display issue on Windows 2023-01-19 20:47:56 +08:00
fengcaiwen
17bc64559b feat: update go mod to 1.19 2023-01-19 19:40:06 +08:00
fengcaiwen
fd7c81a104 feat(upgrade): check permission of current kubevpn folder and pretty download progress bar 2023-01-19 16:48:13 +08:00
fengcaiwen
ac30ed7956 feat(doc): update readme usage 2023-01-19 14:54:13 +08:00
fengcaiwen
74beaceb9f feat: update all go dependency to latest if available 2023-01-17 14:30:02 +08:00
wencaiwulue
87dac42dad feat: warning more human-readable if using sudo to exec kubevpn 2023-01-15 12:09:07 +08:00
wencaiwulue
121ebe07ed feat: just warning instead of exit if using sudo to exec kubevpn 2023-01-14 23:38:23 +08:00
fengcaiwen
74c08e391a feat: refactor code 2023-01-14 21:00:50 +08:00
fengcaiwen
710904b350 feat: add sub-command options to print support global flags 2023-01-14 19:10:18 +08:00
fengcaiwen
21f79e03d8 feat: reflector use context as function first parameter 2023-01-14 17:22:59 +08:00
fengcaiwen
438509ffef feat: support env KUBECONFIG finally 2023-01-14 17:10:34 +08:00
fengcaiwen
d71e51588d Merge remote-tracking branch 'origin/master' 2023-01-14 16:43:56 +08:00
fengcaiwen
faebedad0a feat: use kubectl style new cmd 2023-01-14 16:42:49 +08:00
fengcaiwen
7e5aa5e944 feat: rename 2023-01-12 16:49:36 +08:00
fengcaiwen
8df6c9c0f8 feat: support env KUBECONFIG 2023-01-12 16:48:27 +08:00
fengcaiwen
68c580d636 feat: delete useless test file 2023-01-12 12:39:57 +08:00
fengcaiwen
6f30e2361d feat: close temp file before rename it 2023-01-12 12:37:29 +08:00
wencaiwulue
dfed43c6e9 feat: add sub-command upgrade 2023-01-11 23:11:30 +08:00
wencaiwulue
1786a7965e feat: add sub-command upgrade 2023-01-11 21:37:42 +08:00
wencaiwulue
ecf9fe7353 feat: webhook ignore error and wait all container of pod kubevpn-traffic-manager are ready 2023-01-11 21:34:51 +08:00
fengcaiwen
de8dcd8668 feat: add service ip to dns server list 2023-01-11 20:53:51 +08:00
fengcaiwen
7c85d9a628 feat: support websocket 2023-01-11 20:52:33 +08:00
wencaiwulue
a44f323f23 feat(test): add cache for testcase 2023-01-08 17:28:51 +08:00
fengcaiwen
f6471ef948 feat: use cm data to store ref-count and move control-plane into a subcommand of kubevpn 2023-01-06 19:29:57 +08:00
wencaiwulue
6ee83d6e65 optimize comment 2023-01-05 23:02:48 +08:00
fengcaiwen
45b4c9c98d feat: add sub-command reset 2023-01-05 14:06:09 +08:00
wencaiwulue
1b85450ef4 feat: add usage 2022-12-28 14:56:52 +08:00
wencaiwulue
200637f717 feat: compromise 2022-12-27 15:18:45 +08:00
wencaiwulue
f826357bae feat: optimize check pod status logic for redo port-forward 2022-12-27 11:52:25 +08:00
wencaiwulue
6816c02933 feat: optimize get cidr from pod logic 2022-12-25 16:52:27 +08:00
wencaiwulue
3452a71126 feat: optimize get cidr from pod logic 2022-12-25 16:14:37 +08:00
wencaiwulue
33a1b0add3 feat: delete get cidr pod anyway 2022-12-17 18:33:24 +08:00
fengcaiwen
a07b5cae2e feat: retry dns query 2022-12-14 21:57:31 +08:00
wencaiwulue
dac083e7b3 feat: optimize webhook 2022-12-13 21:56:41 +08:00
fengcaiwen
5a562ee0a1 feat: use webhook to manage ip allocate 2022-12-13 21:35:41 +08:00
wencaiwulue
5d5c6c4717 fix(test): link resolvectl to systemd-resolve 2022-12-11 15:16:18 +08:00
wencaiwulue
b4394ebce3 fix(test): link resolvectl to systemd-resolve 2022-12-11 13:50:15 +08:00
wencaiwulue
182905c8e2 feat: try to collect any cidr we could find 2022-12-11 12:51:05 +08:00
wencaiwulue
e181ea417d feat: add vendor to gitignore 2022-12-11 10:12:53 +08:00
wencaiwulue
8a0290bbd2 feat: docker build with platform 2022-12-11 10:11:43 +08:00
fengcaiwen
8356ff68d2 feat: disable envoy stream timeout 2022-12-09 22:03:42 +08:00
wencaiwulue
1004db36b9 feat: use random port instead of 10800 2022-11-28 20:04:39 +08:00
wencaiwulue
38fa6c44af feat: remove default value of kubeconfig path 2022-11-23 22:32:29 +08:00
wencaiwulue
8e45f49251 feat: optimize get cidr logic 2022-11-23 21:34:30 +08:00
wencaiwulue
331d160085 feat: add missing driver 2022-11-06 23:27:41 +08:00
fengcaiwen
675759803e fix: all in one image and support special image to connect 2022-11-06 22:52:42 +08:00
fengcaiwen
1146d4c440 fix: optimize code 2022-11-06 22:52:42 +08:00
wencaiwulue
6ca3942f4a feat: optimize code 2022-11-06 22:52:42 +08:00
wencaiwulue
86c39699e4 feat: update get cidr pod image 2022-11-06 22:52:42 +08:00
fengcaiwen
2c6f58be7b fix: get service cidr from mounting folder /proc to container 2022-11-06 22:52:42 +08:00
fengcaiwen
f88a2f09cc fix: ignore error of test 2022-11-06 22:52:42 +08:00
fengcaiwen
cb74a7e29e fix: use "" instead of use '' 2022-11-06 22:52:42 +08:00
wencaiwulue
4e4d69b439 feat: update $() --> ${} 2022-11-06 22:52:42 +08:00
wencaiwulue
665a7fe739 feat: update macos-latest --> macos-10.15 2022-11-06 22:52:42 +08:00
wencaiwulue
d17bec03c0 feat: update README.md 2022-11-06 22:52:42 +08:00
wencaiwulue
f5ed4ad976 feat: cp kubevpn to $PATH 2022-11-06 22:52:42 +08:00
wencaiwulue
1fc499d780 feat: optimize testcase 2022-11-06 22:52:42 +08:00
wencaiwulue
d48ba5e9c4 feat: update timeout duration from 10 min to 60 min 2022-11-06 22:52:42 +08:00
wencaiwulue
cad0f586f6 feat: patch once and restore probe by last user exit 2022-11-06 22:52:42 +08:00
wencaiwulue
2066e313b1 feat: get cluster cidr from cni folder 2022-11-06 22:52:42 +08:00
wencaiwulue
aadb4e12c3 feat: add go proxy env 2022-10-30 10:55:22 +08:00
wencaiwulue
75684a307b fix: add dockerfile for building locally 2022-10-29 12:49:58 +08:00
wencaiwulue
c4ee50e35e feat: optimize args 2022-10-29 10:18:36 +08:00
fengcaiwen
7298271c1f feat: optimize args 2022-10-28 22:39:10 +08:00
wencaiwulue
c0c3c6059d fix: get cidr expect hostNetwork 2022-10-26 20:21:42 +08:00
wencaiwulue
a8ef68ae1b Added kubevpn logic.drawio 2022-08-07 11:50:53 +08:00
wencaiwulue
5d2c7cab31 fix: npe 2022-08-06 15:03:18 +08:00
wencaiwulue
7b2e9e1937 feat: rename 2022-08-05 16:17:27 +08:00
wencaiwulue
ada917fa18 feat: reformat logger 2022-08-05 15:57:59 +08:00
wencaiwulue
f74dcb7a7f feat: move folder to pkg 2022-08-05 15:23:34 +08:00
wencaiwulue
1e8abc03ce Merge remote-tracking branch 'origin/master' 2022-08-05 14:33:38 +08:00
wencaiwulue
1ed2064eda feature: Sort import 2022-06-22 10:49:27 +08:00
wencaiwulue
059100e81f Create LICENSE 2022-06-21 19:32:28 +08:00
wencaiwulue
e1f8510ddc update image pull policy from PullAlways to PullIfNotPresent 2022-05-12 17:17:56 +08:00
wencaiwulue
6598c2ddef try to fix can not get tag issue 2022-05-05 19:20:25 +08:00
wencaiwulue
0db81f379d update GitHub action runner os from macos to ubuntu 2022-05-05 19:14:34 +08:00
wencaiwulue
e44a08404c fix release changelog bug 2022-05-05 17:01:14 +08:00
wencaiwulue
26f07c3fba fix release changelog bug 2022-05-05 16:16:26 +08:00
wencaiwulue
e813cc2ac2 add release changelog 2022-05-05 16:10:08 +08:00
wencaiwulue
afa76a0687 get service cidr by creating a service with clusterIP 0.0.0.0, parse error message The range of valid IPs is xxx.xxx.xxx.xxx 2022-05-01 10:00:09 +08:00
p_caiwfeng
3ded40706a add demo 2022-04-20 15:32:04 +08:00
p_caiwfeng
2f47a05b85 update go version to 1.18 2022-04-20 14:16:30 +08:00
p_caiwfeng
2043ab3f1b speed up fail if port-forward occurs error 2022-04-08 14:54:07 +08:00
p_caiwfeng
e34b1c99ab set wait pod to be ready timeout to 1 hour 2022-04-07 16:16:55 +08:00
p_caiwfeng
7cc2fb72fd detect pod delete event, if pod is deleted needs to redo port-forward immediately 2022-04-07 16:12:08 +08:00
p_caiwfeng
008b228746 avoid tcp to send multiple small package 2022-04-07 14:03:08 +08:00
p_caiwfeng
6d5597c977 optimize code 2022-04-07 09:47:51 +08:00
p_caiwfeng
6d4970d6f4 modify testcase timeout from 10 min to 2 hours 2022-04-06 17:40:11 +08:00
p_caiwfeng
353d560825 typo 2022-04-06 16:11:48 +08:00
p_caiwfeng
3d41967c3e typo 2022-04-06 15:57:14 +08:00
p_caiwfeng
7e53c1659a optimize slice usage 2022-04-06 15:49:48 +08:00
p_caiwfeng
9fae2e8e0e optimize code 2022-04-05 17:37:06 +08:00
p_caiwfeng
619e2ce304 use statefulset to control pod 2022-04-05 16:01:24 +08:00
p_caiwfeng
2a6c8f8fb3 optimize code 2022-04-02 11:23:18 +08:00
p_caiwfeng
4c34d85393 remove useless config 2022-03-19 21:23:49 +08:00
p_caiwfeng
43ca8452de optimize code 2022-03-14 17:59:05 +08:00
p_caiwfeng
b834db457d optimize logic 2022-03-14 17:59:05 +08:00
p_caiwfeng
96da83e37d fix typo 2022-03-09 22:22:34 +08:00
p_caiwfeng
a1401d8eed fix flags not work issue 2022-03-09 22:15:44 +08:00
p_caiwfeng
3905e093b5 pull image previous 2022-03-09 18:27:10 +08:00
wencaiwulue
4820c98a96 update readme service mesh support multiple port 2022-03-09 16:48:43 +08:00
wencaiwulue
8835ace656 move cleanup configmap to last step in case of remove some config not found cm 2022-03-09 16:47:23 +08:00
p_caiwfeng
5d60b4912b support multiple port with envoy 2022-03-07 20:41:04 +08:00
p_caiwfeng
b6e0b7ce52 support multiple port with envoy 2022-03-07 20:41:04 +08:00
p_caiwfeng
a48a256bdc support multiple port with envoy 2022-03-07 20:41:04 +08:00
p_caiwfeng
e7a9d28a6c optimize iptables 2022-03-01 22:40:32 +08:00
p_caiwfeng
b3d67cf6ce image use kubevpn version 2022-02-28 14:40:59 +08:00
p_caiwfeng
816980e4f2 fix testcase 2022-02-28 12:10:16 +08:00
p_caiwfeng
0051168776 change server port to 8422 from 8421 2022-02-28 11:46:21 +08:00
p_caiwfeng
45f4831b50 works fine 2022-02-23 17:33:19 +08:00
p_caiwfeng
1248527045 remove dst addr from tcp traffic header for performance 2022-02-23 17:19:56 +08:00
p_caiwfeng
c7c929da12 rename 2022-02-22 13:57:53 +08:00
p_caiwfeng
8b0b3b9b25 use ipam to optimize dhcp 2022-02-21 16:47:22 +08:00
p_caiwfeng
dae72fdb8d exchange mode support port-forward 2022-02-20 11:26:11 +08:00
wencaiwulue
ff31810ed5 fix release tag issue 2022-02-19 20:52:02 +08:00
wencaiwulue
b3a0ddd7e7 optimize parse groupVersion 2022-02-19 16:27:50 +08:00
p_caiwfeng
51515607dc fix can not get tag issue 2022-02-16 14:26:08 +08:00
p_caiwfeng
a69ed17fe1 move kubevpn connect logic from method init to before testcase start 2022-02-16 14:00:16 +08:00
p_caiwfeng
4f0da2803f update github token for repository-dispatch 2022-02-16 11:10:22 +08:00
p_caiwfeng
cebd3f7623 update docker login url 2022-02-16 10:53:49 +08:00
p_caiwfeng
a2f6c26101 optimize Makefile 2022-02-16 10:44:49 +08:00
p_caiwfeng
a27f9d6779 fix testcase 2022-02-16 09:34:41 +08:00
p_caiwfeng
cee42b2900 support arm64 and 386 2022-02-15 17:37:49 +08:00
p_caiwfeng
1c55e92e1a update get route table on linux go build 2022-02-15 09:38:58 +08:00
wencaiwulue
39d3bfe29e optimize Makefile 2022-02-14 20:46:51 +08:00
wencaiwulue
4e7f0eb901 optimize release.yml 2022-02-14 20:25:14 +08:00
wencaiwulue
b2bb9cc041 update release.yal 2022-02-14 20:06:53 +08:00
p_caiwfeng
e2f096023b optimize interact logic 2022-02-14 19:10:41 +08:00
p_caiwfeng
c6e3937f8b optimize intersect logic 2022-02-13 21:27:20 +08:00
p_caiwfeng
c7ba43558e optimize intersect logic 2022-02-13 21:00:45 +08:00
p_caiwfeng
f0780cf3ce optimize intersect logic 2022-02-13 20:41:19 +08:00
wencaiwulue
5b240473d1 update todo.md 2022-02-13 19:27:39 +08:00
wencaiwulue
7fe3c29265 support detect conflict route device on macOS and linux 2022-02-13 19:22:44 +08:00
p_caiwfeng
bd2c2617ee fix GitHub action not correct issue 2022-02-12 22:09:28 +08:00
p_caiwfeng
0666313b73 disable eth device while have conflict route with utun on macOS 2022-02-12 22:07:07 +08:00
p_caiwfeng
399950b8be remove testcase for Windows because can not set up kubernetes 2022-02-12 18:08:27 +08:00
p_caiwfeng
2548e494b3 update DNS timeout from 2 seconds to 5 seconds 2022-02-12 18:04:42 +08:00
wencaiwulue
04af3deb0d use virtualbox as kubernetes driver on Windows 2022-02-10 14:44:36 +08:00
wencaiwulue
457649aa4f try to create minikube on Windows 2022-02-10 14:27:13 +08:00
wencaiwulue
9c75cf87a4 pull image before test start 2022-02-10 14:08:01 +08:00
p_caiwfeng
4fdb515e04 fix can't remove mesh container totally bug 2022-02-09 20:23:35 +08:00
wencaiwulue
05f235617f update readme 2022-02-09 18:12:26 +08:00
wencaiwulue
f891cc1745 update build timestamp format 2022-02-08 20:51:38 +08:00
p_caiwfeng
c9c85700de add version 2022-02-08 15:54:27 +08:00
p_caiwfeng
9f477e0806 optimize get CIDR logic 2022-02-08 10:48:27 +08:00
13987 changed files with 3558669 additions and 8450 deletions

102
.github/krew.yaml vendored Normal file
View File

@@ -0,0 +1,102 @@
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
name: kubevpn
spec:
version: {{ .TagName }}
homepage: https://github.com/kubenetworks/kubevpn
shortDescription: "KubeVPN offers a Cloud Native Dev Environment that connects to kubernetes cluster network"
description: |
KubeVPN offers a Cloud-Native Dev Environment that seamlessly connects to your Kubernetes cluster network.
Gain access to the Kubernetes cluster network effortlessly using service names or Pod IP/Service IP. Facilitate the interception of inbound traffic from remote Kubernetes cluster services to your local PC through a service mesh and more.
For instance, you have the flexibility to run your Kubernetes pod within a local Docker container, ensuring an identical environment, volume, and network setup. With KubeVPN, empower yourself to develop applications entirely on your local PC!
platforms:
- selector:
matchLabels:
os: windows
arch: amd64
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_windows_amd64.zip" .TagName }}
files:
- from: ./bin/kubevpn.exe
to: .
- from: LICENSE
to: .
bin: kubevpn.exe
- selector:
matchLabels:
os: windows
arch: arm64
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_windows_arm64.zip" .TagName }}
files:
- from: ./bin/kubevpn.exe
to: .
- from: LICENSE
to: .
bin: kubevpn.exe
- selector:
matchLabels:
os: windows
arch: 386
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_windows_386.zip" .TagName }}
files:
- from: ./bin/kubevpn.exe
to: .
- from: LICENSE
to: .
bin: kubevpn.exe
- selector:
matchLabels:
os: linux
arch: amd64
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_linux_amd64.zip" .TagName }}
files:
- from: ./bin/kubevpn
to: .
- from: LICENSE
to: .
bin: kubevpn
- selector:
matchLabels:
os: linux
arch: arm64
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_linux_arm64.zip" .TagName }}
files:
- from: ./bin/kubevpn
to: .
- from: LICENSE
to: .
bin: kubevpn
- selector:
matchLabels:
os: linux
arch: 386
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_linux_386.zip" .TagName }}
files:
- from: ./bin/kubevpn
to: .
- from: LICENSE
to: .
bin: kubevpn
- selector:
matchLabels:
os: darwin
arch: amd64
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_darwin_amd64.zip" .TagName }}
files:
- from: ./bin/kubevpn
to: .
- from: LICENSE
to: .
bin: kubevpn
- selector:
matchLabels:
os: darwin
arch: arm64
{{addURIAndSha "https://github.com/kubenetworks/kubevpn/releases/download/{{ .TagName }}/kubevpn_{{ .TagName }}_darwin_arm64.zip" .TagName }}
files:
- from: ./bin/kubevpn
to: .
- from: LICENSE
to: .
bin: kubevpn

76
.github/release-note.sh vendored Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
RELEASE=${RELEASE:-$2}
PREVIOUS_RELEASE=${PREVIOUS_RELEASE:-$1}
# ref https://stackoverflow.com/questions/1441010/the-shortest-possible-output-from-git-log-containing-author-and-date
CHANGELOG=$(git log --no-merges --date=short --pretty=format:'- %h %an %ad %s' "${PREVIOUS_RELEASE}".."${RELEASE}")
cat <<EOF
# KubeVPN release ${RELEASE}
KubeVPN ${RELEASE} is available now ! 🎉
## Download KubeVPN for your platform
**Mac** (x86-64/Intel)
\`\`\`
curl -Lo kubevpn.zip https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_darwin_amd64.zip && unzip -d kubevpn kubevpn.zip
\`\`\`
**Mac** (AArch64/Apple M1 silicon)
\`\`\`
curl -Lo kubevpn.zip https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_darwin_arm64.zip && unzip -d kubevpn kubevpn.zip
\`\`\`
**Linux** (x86-64)
\`\`\`
curl -Lo kubevpn.zip https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_linux_amd64.zip && unzip -d kubevpn kubevpn.zip
\`\`\`
**Linux** (AArch64)
\`\`\`
curl -Lo kubevpn.zip https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_linux_arm64.zip && unzip -d kubevpn kubevpn.zip
\`\`\`
**Linux** (i386)
\`\`\`
curl -Lo kubevpn.zip https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_linux_386.zip && unzip -d kubevpn kubevpn.zip
\`\`\`
**Windows** (x86-64)
\`\`\`
curl -LO https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_windows_amd64.zip
\`\`\`
**Windows** (AArch64)
\`\`\`
curl -LO https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_windows_arm64.zip
\`\`\`
**Windows** (i386)
\`\`\`
curl -LO https://github.com/kubenetworks/kubevpn/releases/download/${RELEASE}/kubevpn_${RELEASE}_windows_386.zip
\`\`\`
## Checksums
SHA256 checksums available for compiled binaries.
Run \`shasum -a 256 -c checksums.txt\` to verify.
## Upgrading
Run \`kubevpn upgrade\` to upgrade from a previous version.
## Changelog
${CHANGELOG}
EOF

79
.github/workflows/coverage.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: Coverage
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
check-latest: true
- name: Setup Minikube
id: minikube
timeout-minutes: 30
uses: medyagh/setup-minikube@latest
with:
cache: true
cpus: 'max'
memory: 'max'
- name: Kubernetes info
run: |
kubectl cluster-info
cat ~/.kube/config
kubectl get pods -n kube-system -o wide
- name: Install demo bookinfo
run: |
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-details-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-ratings-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-reviews-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-productpage-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/authors:latest
minikube image load --remote ghcr.io/kubenetworks/nginx:latest
minikube image ls
eval $(minikube docker-env)
kubectl apply -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
- name: Build
run: |
export VERSION=${{github.event.pull_request.head.sha}}
if [[ -z "$VERSION" ]]; then
export VERSION=${{ github.sha }}
fi
make kubevpn-linux-amd64
chmod +x ./bin/kubevpn
cp ./bin/kubevpn /usr/local/bin/kubevpn
kubevpn version
- name: Wait for pods reviews to be ready
run: |
kubectl wait --for=condition=Ready pods --all --timeout=3600s
kubectl get svc -A -o wide
kubectl get pod -A -o wide
kubectl get all -o wide
kubectl get nodes -o yaml
ifconfig
route -n
sudo ln /usr/bin/resolvectl /usr/bin/systemd-resolve
- name: Test
run: make ut
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # v4.0.2
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
verbose: true
slug: wencaiwulue/kubevpn

View File

@@ -1,125 +0,0 @@
name: Go
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Setup Minikube
timeout-minutes: 30
uses: medyagh/setup-minikube@master
- name: Kubernetes info
run: |
kubectl cluster-info
cat ~/.kube/config
kubectl get pods -n kube-system -o wide
- name: Install demo bookinfo
run: kubectl apply -f https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/bookinfo.yaml
- name: Build
run: make kubevpn-linux
- name: Wait for pods reviews to be ready
run: |
kubectl wait pods -l app=reviews --for=condition=Ready --timeout=600s
kubectl get all -o wide
kubectl get nodes -o yaml
ifconfig
route -n
- name: Test
run: go test -v ./test/
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- uses: docker-practice/actions-setup-docker@master
- run: |
rm '/usr/local/bin/kubectl'
set -x
docker version
docker run --rm hello-world
- run: |
brew install minikube
minikube start --driver=docker
kubectl get po -A
minikube kubectl -- get po -A
- name: Kubernetes info
run: |
kubectl cluster-info
cat ~/.kube/config
kubectl get pods -n kube-system -o wide
- name: Install demo bookinfo
run: kubectl apply -f https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/bookinfo.yaml
- name: Build
run: make kubevpn-macos
- name: Wait for pods reviews to be ready
run: |
kubectl wait pods -l app=reviews --for=condition=Ready --timeout=600s
kubectl get all -o wide
kubectl get nodes -o yaml
ifconfig
- name: Test
run: go test -v ./test/
# windows:
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v2
#
# - name: Set up Go
# uses: actions/setup-go@v2
# with:
# go-version: 1.17
# - uses: docker-practice/actions-setup-docker@master
# - run: |
# docker version
# docker run --rm hello-world
# - run: |
# winget install minikube
# minikube start --driver=docker
# minikube kubectl -- get po -A
# choco install make
# - name: Kubernetes info
# run: |
# kubectl cluster-info dump
# kubectl get pods -n kube-system -o wide
# - name: Install demo bookinfo
# run: kubectl apply -f https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/bookinfo.yaml
#
# - name: Build
# run: make kubevpn-windows
#
# - name: Wait for pods reviews to be ready
# run: |
# kubectl wait pods -l app=reviews --for=condition=Ready --timeout=600s
# kubectl get all -o wide
# kubectl get nodes -o yaml
# ipconfig
#
# - name: Test
# run: go test -v ./test/

View File

@@ -11,11 +11,29 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: 1.17
go-version: '1.23'
check-latest: true
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Push image to docker hub
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USER }} --password-stdin
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker buildx create --use
make container
- name: Release Note
run: |
RELEASE_VERSION=${GITHUB_REF#refs/*/}
PREVERSION=$(git for-each-ref --sort='-creatordate' --format='%(refname:lstrip=2)' --count=50 'refs/tags/*' | grep -v 'rc' | awk 'NR==2')
echo ${PREVERSION}
echo ${PREVERSION}
echo "$(./.github/release-note.sh ${PREVERSION} ${RELEASE_VERSION})" > release_note.md
- name: Create Release
id: create_release
uses: actions/create-release@v1
@@ -24,12 +42,9 @@ jobs:
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: |
Changes in this Release
- First Change
- Second Change
draft: false
prerelease: false
body_path: release_note.md
- name: Collect Release Info
run: |
@@ -38,48 +53,211 @@ jobs:
git reset --hard
- name: Upload RELEASE_VERSION
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: RELEASE_VERSION
path: RELEASE_VERSION
- name: Upload UPLOAD_URL
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: UPLOAD_URL
path: UPLOAD_URL
- name: Build kubevpn-linux
run: make kubevpn-linux
- name: Upload Release Asset
- name: Repository Dispatch
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: Upload_release
token: ${{ secrets.REPOSITORYDISPATCH }}
inputs: '{"url": "${{ steps.create_release.outputs.upload_url }}", "tag": "${{ github.ref_name }}"}'
- name: Make changes to pull request
run: make version && echo ${GITHUB_REF#refs/*/} > plugins/stable.txt
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v4
with:
add-paths: |
*.yaml
plugins/stable.txt
token: ${{ secrets.REPOSITORYDISPATCH }}
commit-message: "feat: update krew index version to ${{ github.ref }}"
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: feat/update-krew-index-version
base: master
delete-branch: true
title: 'feat: update krew index version to ${{ github.ref }}'
body: |
update report
- update with *today's* date
- update krew index version to ${{ github.ref }}
labels: |
report
automated pr
draft: false
release-helm-chart:
name: Release KubeVPN Helm Chart
needs: [ build ]
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
check-latest: true
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Helm tool installer
uses: azure/setup-helm@v4
with:
version: "v3.6.3"
- name: Change chart version
run: |
VERSION=${GITHUB_REF#refs/*/}
CHART_VERSION=${VERSION/#v/}
sed -i "s/^appVersion:.*$/appVersion: \"${VERSION}\"/;s/^version:.*$/version: ${CHART_VERSION}/" charts/kubevpn/Chart.yaml
sed -i "s/tag:.*$/tag: \"${VERSION}\"/" charts/kubevpn/values.yaml
- name: Tar chart
run: |
VERSION=${GITHUB_REF#refs/*/}
CHART_VERSION=${VERSION/#v/}
tar --transform 's/^charts\/kubevpn/kubevpn/' -zcf kubevpn-${CHART_VERSION}.tgz charts/kubevpn
shasum -a 256 kubevpn-${CHART_VERSION}.tgz | awk '{print $1}' > kubevpn-${CHART_VERSION}.tgz-SHA256
- name: Download UPLOAD_URL
uses: actions/download-artifact@v4
with:
name: UPLOAD_URL
- name: Get Release UPLOAD_URL
id: get_release_info
run: |
UploadUrl=$(cat ./UPLOAD_URL)
echo "::set-output name=upload_url::$UploadUrl"
- name: Get assert name
id: get_assert_info
run: |
VERSION=${GITHUB_REF#refs/*/}
CHART_VERSION=${VERSION/#v/}
AssertName=kubevpn-${CHART_VERSION}.tgz
echo "::set-output name=assert_name::$AssertName"
- name: Get assert SHA256 name
id: get_assert_info_sha256
run: |
VERSION=${GITHUB_REF#refs/*/}
CHART_VERSION=${VERSION/#v/}
AssertName=kubevpn-${CHART_VERSION}.tgz-SHA256
echo "::set-output name=assert_name::$AssertName"
- name: Upload Release Asset KubeVPN Server Chart
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: kubevpn
asset_name: kubevpn-linux-amd64
upload_url: ${{ steps.get_release_info.outputs.upload_url }}
asset_path: ${{ steps.get_assert_info.outputs.assert_name }}
asset_name: ${{ steps.get_assert_info.outputs.assert_name }}
asset_content_type: application/octet-stream
- name: Upload Release Asset KubeVPN Chart SHA256
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.get_release_info.outputs.upload_url }}
asset_path: ${{ steps.get_assert_info_sha256.outputs.assert_name }}
asset_name: ${{ steps.get_assert_info_sha256.outputs.assert_name }}
asset_content_type: application/octet-stream
- name: Build kubevpn-macos
run: make kubevpn-macos
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
github-pages-deploy:
name: Release Helm Chart To branch master
permissions:
contents: write
runs-on: ubuntu-latest
needs: release-helm-chart
steps:
- name: Set up Go
uses: actions/setup-go@v5
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: kubevpn
asset_name: kubevpn-darwin-amd64
asset_content_type: application/octet-stream
go-version: '1.23'
check-latest: true
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
- name: Change chart version
run: |
VERSION=${GITHUB_REF#refs/*/}
CHART_VERSION=${VERSION/#v/}
sed -i "s/^appVersion:.*$/appVersion: \"${VERSION}\"/;s/^version:.*$/version: ${CHART_VERSION}/" charts/kubevpn/Chart.yaml
sed -i "s/tag:.*$/tag: \"${VERSION}\"/" charts/kubevpn/values.yaml
- name: Package and upload helm chart
run: |
# download helm chart releaser
curl -sSLo cr.tar.gz "https://github.com/helm/chart-releaser/releases/download/v1.6.1/chart-releaser_1.6.1_linux_amd64.tar.gz"
tar -xzf cr.tar.gz
rm -f cr.tar.gz
owner=$(cut -d '/' -f 1 <<< "$GITHUB_REPOSITORY")
repo=$(cut -d '/' -f 2 <<< "$GITHUB_REPOSITORY")
# package chart
./cr package charts/$repo
# update index and push to github pages
git config user.email "$owner@users.noreply.github.com"
git config user.name "$owner"
./cr index \
--owner "$owner" \
--git-repo "$repo" \
--token "${{ secrets.CREATE_HELM_PR }}" \
--release-name-template "v{{ .Version }}" \
--index-path ./index.yaml \
--charts-repo https://github.com/$owner/$repo \
--pages-branch master \
--pages-index-path charts/index.yaml \
--pr
snapcraft:
runs-on: ubuntu-24.04
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
steps:
- name: Check out Git repository
uses: actions/checkout@v3
- name: Build kubevpn-windows
run: make kubevpn-windows
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: kubevpn.exe
asset_name: kubevpn-windows-amd64.exe
asset_content_type: application/octet-stream
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@v3
- name: Setup LXD
uses: canonical/setup-lxd@main
- name: Use Snapcraft
run: |
RELEASE_VERSION=${GITHUB_REF#refs/*/}
sed -i s#CRAFT_ARCH_BUILD_VERSION#$RELEASE_VERSION#g snap/snapcraft.yaml
snapcraft
snapcraft upload --release=stable kubevpn_${RELEASE_VERSION}_amd64.snap
snapcraft-arm:
runs-on: ubuntu-24.04-arm
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
steps:
- name: Check out Git repository
uses: actions/checkout@v3
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@v3
- name: Setup LXD
uses: canonical/setup-lxd@main
- name: Use Snapcraft
run: |
RELEASE_VERSION=${GITHUB_REF#refs/*/}
sed -i s#CRAFT_ARCH_BUILD_VERSION#$RELEASE_VERSION#g snap/snapcraft.yaml
snapcraft
snapcraft upload --release=stable kubevpn_${RELEASE_VERSION}_arm64.snap

198
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,198 @@
name: Test
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
check-latest: true
- name: Push image to docker hub
run: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
export VERSION=${{github.event.pull_request.head.sha}}
if [[ -z "$VERSION" ]]; then
export VERSION=${{ github.sha }}
fi
make container-test
linux:
runs-on: ubuntu-latest
needs: [ "image" ]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
check-latest: true
- name: Setup Minikube
id: minikube
timeout-minutes: 30
uses: medyagh/setup-minikube@latest
with:
cache: true
cpus: 'max'
memory: 'max'
- name: Kubernetes info
run: |
kubectl cluster-info
cat ~/.kube/config
kubectl get pods -n kube-system -o wide
- name: Install demo bookinfo
run: |
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-details-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-ratings-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-reviews-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/examples-bookinfo-productpage-v1:1.20.2
minikube image load --remote ghcr.io/kubenetworks/authors:latest
minikube image load --remote ghcr.io/kubenetworks/nginx:latest
minikube image ls
eval $(minikube docker-env)
kubectl apply -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
- name: Build
run: |
export VERSION=${{github.event.pull_request.head.sha}}
if [[ -z "$VERSION" ]]; then
export VERSION=${{ github.sha }}
fi
make kubevpn-linux-amd64
chmod +x ./bin/kubevpn
cp ./bin/kubevpn /usr/local/bin/kubevpn
kubevpn version
- name: Wait for pods reviews to be ready
run: |
kubectl wait --for=condition=Ready pods --all --timeout=3600s
kubectl get svc -A -o wide
kubectl get pod -A -o wide
kubectl get all -o wide
kubectl get nodes -o yaml
ifconfig
route -n
sudo ln /usr/bin/resolvectl /usr/bin/systemd-resolve
- name: Test
run: make ut
macos:
runs-on: macos-13
needs: [ "image" ]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
check-latest: true
# https://github.com/crazy-max/ghaction-setup-docker/issues/108
- name: Set up QEMU
uses: docker/actions-toolkit/.github/actions/macos-setup-qemu@19ca9ade20f5da695f76a10988d6532058575f82
- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
daemon-config: |
{
"debug": true,
"features": {
"containerd-snapshotter": true
}
}
- uses: azure/setup-kubectl@v4
- name: Install minikube
uses: medyagh/setup-minikube@latest
with:
cache: true
cpus: 'max'
memory: 'max'
- name: Kubernetes info
run: |
kubectl config view --flatten --raw
kubectl get pod -A -o wide
kubectl cluster-info
cat ~/.kube/config
kubectl get pods -n kube-system -o wide
- name: Install demo bookinfo
run: |
kubectl apply -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
- name: Build
run: |
export VERSION=${{github.event.pull_request.head.sha}}
if [[ -z "$VERSION" ]]; then
export VERSION=${{ github.sha }}
fi
make kubevpn-darwin-amd64
chmod +x ./bin/kubevpn
cp ./bin/kubevpn /usr/local/bin/kubevpn
kubevpn version
- name: Wait for pods reviews to be ready
run: |
kubectl wait --for=condition=Ready pods --all --timeout=3600s
kubectl get svc -A -o wide || true
kubectl get pod -A -o wide || true
kubectl get all -o wide || true
kubectl get nodes -o yaml || true
ifconfig
netstat -anr
- name: Test
run: make ut
windows:
runs-on: windows-latest
env:
VERSION: ${{ github.event.pull_request.head.sha || github.sha }}
needs: [ "image" ]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
daemon-config: |
{
"debug": true,
"features": {
"containerd-snapshotter": true
}
}
- run: |
docker info --format '{{.OSType}}'
choco install kind
kind create cluster
kubectl cluster-info
kubectl config view --flatten --raw
- run: |
choco install minikube
minikube start --driver=docker
choco install make
- name: Build
run: |
make kubevpn-windows-amd64
./bin/kubevpn.exe version
./bin/kubevpn.exe status

55
.github/workflows/upload_release.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Upload_release
on:
workflow_dispatch:
inputs:
url:
description: 'github release url'
required: true
tag:
description: 'latest tag'
required: true
jobs:
build:
name: Create Release
runs-on: ubuntu-latest
strategy:
matrix:
os: [ darwin, windows, linux ]
arch: [ amd64, arm64, 386 ]
exclude:
- os: darwin
arch: 386
steps:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
check-latest: true
- name: Checkout code
uses: actions/checkout@v4
- name: Build kubevpn
run: |
git tag ${{ github.event.inputs.tag }} || true
export GitHubOAuthToken=${{ secrets.KUBEVPN_UPGRADE_OAUTH }}
make kubevpn-${{ matrix.os }}-${{ matrix.arch }}
SUFFIX=""
if [ "${{ matrix.os }}" = "windows" ]; then
SUFFIX=".exe"
fi
shasum -a 256 ./bin/kubevpn${SUFFIX} | awk '{print $1}' > checksums.txt
zip -r kubevpn_${{ github.event.inputs.tag }}_${{ matrix.os }}_${{ matrix.arch }}.zip ./bin/kubevpn${SUFFIX} LICENSE README.md README_ZH.md checksums.txt
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.inputs.url }}
asset_path: ./kubevpn_${{ github.event.inputs.tag }}_${{ matrix.os }}_${{ matrix.arch }}.zip
asset_name: kubevpn_${{ github.event.inputs.tag }}_${{ matrix.os }}_${{ matrix.arch }}.zip
asset_content_type: application/zip

6
.gitignore vendored
View File

@@ -1,8 +1,6 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
@@ -19,4 +17,6 @@
.vscode/
# Build artifacts
kubevpn
bin
*.DS_Store

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 wencaiwulue
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

138
Makefile
View File

@@ -1,38 +1,114 @@
.PHONY: kubevpn-macos
kubevpn-macos:
go build -o kubevpn github.com/wencaiwulue/kubevpn/cmd/kubevpn
chmod +x kubevpn
cp kubevpn /usr/local/bin/kubevpn
VERSION ?= $(shell git tag -l --sort=v:refname | tail -1)
GIT_COMMIT ?= $(shell git describe --match=NeVeRmAtCh --always --abbrev=7)
BUILD_TIME ?= $(shell date +"%Y-%m-%dT%H:%M:%SZ")
BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
.PHONY: kubevpn-windows
kubevpn-windows:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o kubevpn.exe github.com/wencaiwulue/kubevpn/cmd/kubevpn
GOOS := $(shell go env GOHOSTOS)
GOARCH := $(shell go env GOHOSTARCH)
TARGET := kubevpn-${GOOS}-${GOARCH}
OS_ARCH := ${GOOS}/${GOARCH}
.PHONY: kubevpn-linux
kubevpn-linux:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o kubevpn github.com/wencaiwulue/kubevpn/cmd/kubevpn
chmod +x kubevpn
cp kubevpn /usr/local/bin/kubevpn
BASE := github.com/wencaiwulue/kubevpn/v2
FOLDER := ${BASE}/cmd/kubevpn
BUILD_DIR ?= ./build
OUTPUT_DIR ?= ./bin
REGISTRY ?= docker.io
NAMESPACE ?= naison
REPOSITORY ?= kubevpn
IMAGE ?= $(REGISTRY)/$(NAMESPACE)/$(REPOSITORY):$(VERSION)
IMAGE_LATEST ?= docker.io/naison/kubevpn:latest
IMAGE_GH ?= ghcr.io/kubenetworks/kubevpn:$(VERSION)
IMAGE_GH_LATEST ?= ghcr.io/kubenetworks/kubevpn:latest
.PHONY: control-plane-linux
control-plane-linux:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o envoy-xds-server github.com/wencaiwulue/kubevpn/pkg/controlplane/cmd/server
chmod +x envoy-xds-server
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS=--ldflags "-s -w\
-X ${BASE}/pkg/config.Image=${IMAGE_GH} \
-X ${BASE}/pkg/config.Version=${VERSION} \
-X ${BASE}/pkg/config.GitCommit=${GIT_COMMIT} \
-X ${BASE}/pkg/config.GitHubOAuthToken=${GitHubOAuthToken} \
-X ${FOLDER}/cmds.BuildTime=${BUILD_TIME} \
-X ${FOLDER}/cmds.Branch=${BRANCH} \
-X ${FOLDER}/cmds.OsArch=${OS_ARCH} \
"
.PHONY: image
image: kubevpn-linux
docker build -t naison/kubevpn:v2 -f ./dockerfile/server/Dockerfile .
rm -fr kubevpn
docker push naison/kubevpn:v2
GO111MODULE=on
GOPROXY=https://goproxy.cn,direct
.PHONY: image_mesh
image_mesh:
docker build -t naison/kubevpnmesh:v2 -f ./dockerfile/mesh/Dockerfile .
docker push naison/kubevpnmesh:v2
.PHONY: all
all: kubevpn-all container
.PHONY: image_control_plane
image_control_plane: control-plane-linux
docker build -t naison/envoy-xds-server:latest -f ./dockerfile/controlplane/Dockerfile .
rm -fr envoy-xds-server
docker push naison/envoy-xds-server:latest
.PHONY: kubevpn-all
kubevpn-all: kubevpn-darwin-amd64 kubevpn-darwin-arm64 \
kubevpn-windows-amd64 kubevpn-windows-386 kubevpn-windows-arm64 \
kubevpn-linux-amd64 kubevpn-linux-386 kubevpn-linux-arm64
.PHONY: kubevpn
kubevpn:
make $(TARGET)
# ---------darwin-----------
.PHONY: kubevpn-darwin-amd64
kubevpn-darwin-amd64:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn ${FOLDER}
chmod +x $(OUTPUT_DIR)/kubevpn
.PHONY: kubevpn-darwin-arm64
kubevpn-darwin-arm64:
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn ${FOLDER}
chmod +x $(OUTPUT_DIR)/kubevpn
# ---------darwin-----------
# ---------windows-----------
.PHONY: kubevpn-windows-amd64
kubevpn-windows-amd64:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn.exe ${FOLDER}
.PHONY: kubevpn-windows-arm64
kubevpn-windows-arm64:
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn.exe ${FOLDER}
.PHONY: kubevpn-windows-386
kubevpn-windows-386:
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn.exe ${FOLDER}
# ---------windows-----------
# ---------linux-----------
.PHONY: kubevpn-linux-amd64
kubevpn-linux-amd64:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn ${FOLDER}
chmod +x $(OUTPUT_DIR)/kubevpn
.PHONY: kubevpn-linux-arm64
kubevpn-linux-arm64:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn ${FOLDER}
chmod +x $(OUTPUT_DIR)/kubevpn
.PHONY: kubevpn-linux-386
kubevpn-linux-386:
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build ${LDFLAGS} -o $(OUTPUT_DIR)/kubevpn ${FOLDER}
chmod +x $(OUTPUT_DIR)/kubevpn
# ---------linux-----------
.PHONY: container
container:
docker buildx build --platform linux/amd64,linux/arm64 -t ${IMAGE} -t ${IMAGE_LATEST} -t ${IMAGE_GH} -t ${IMAGE_GH_LATEST} -f $(BUILD_DIR)/Dockerfile --push .
############################ build local
.PHONY: container-local
container-local: kubevpn-linux-amd64
docker buildx build --platform linux/amd64,linux/arm64 -t ${IMAGE_LATEST} -t ${IMAGE_GH_LATEST} -f $(BUILD_DIR)/local.Dockerfile --push .
.PHONY: container-test
container-test: kubevpn-linux-amd64
docker build -t ${IMAGE_GH} -f $(BUILD_DIR)/test.Dockerfile --push .
.PHONY: version
version:
go run ${BASE}/pkg/util/krew
.PHONY: gen
gen:
go generate ./...
.PHONY: ut
ut:
go test -p=1 -v -timeout=60m -coverprofile=coverage.txt -coverpkg=./... ./...
.PHONY: cover
cover: ut
go tool cover -html=coverage.txt

694
README.md
View File

@@ -1,93 +1,204 @@
![kubevpn](https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/flat_log.png)
[![GitHub Workflow][1]](https://github.com/kubenetworks/kubevpn/actions)
[![Go Version][2]](https://github.com/kubenetworks/kubevpn/blob/master/go.mod)
[![Go Report][3]](https://goreportcard.com/report/github.com/wencaiwulue/kubevpn)
[![Maintainability][4]](https://codeclimate.com/github/kubenetworks/kubevpn/maintainability)
[![GitHub License][5]](https://github.com/kubenetworks/kubevpn/blob/main/LICENSE)
[![Docker Pulls][6]](https://hub.docker.com/r/naison/kubevpn)
[![Releases][7]](https://github.com/kubenetworks/kubevpn/releases)
[![GoDoc](https://godoc.org/github.com/kubenetworks/kubevpn?status.png)](https://pkg.go.dev/github.com/wencaiwulue/kubevpn/v2)
[![codecov](https://codecov.io/gh/wencaiwulue/kubevpn/graph/badge.svg?token=KMDSINSDEP)](https://codecov.io/gh/wencaiwulue/kubevpn)
[![Snapcraft](https://snapcraft.io/kubevpn/badge.svg)](https://snapcraft.io/kubevpn)
[1]: https://img.shields.io/github/actions/workflow/status/kubenetworks/kubevpn/release.yml?logo=github
[2]: https://img.shields.io/github/go-mod/go-version/kubenetworks/kubevpn?logo=go
[3]: https://goreportcard.com/badge/github.com/wencaiwulue/kubevpn?style=flat
[4]: https://api.codeclimate.com/v1/badges/b5b30239174fc6603aca/maintainability
[5]: https://img.shields.io/github/license/kubenetworks/kubevpn
[6]: https://img.shields.io/docker/pulls/naison/kubevpn?logo=docker
[7]: https://img.shields.io/github/v/release/kubenetworks/kubevpn?logo=smartthings
# KubeVPN
[中文](README_ZH.md) | [English](README.md) | [Wiki](https://github.com/wencaiwulue/kubevpn/wiki/Architecture)
[中文](README_ZH.md) | [English](README.md) | [Wiki](https://github.com/kubenetworks/kubevpn/wiki/Architecture)
A tools which can connect to kubernetes cluster network, you can access remote kubernetes cluster network, remote
kubernetes cluster service can also access your local service
KubeVPN offers a Cloud-Native Dev Environment that seamlessly connects to your Kubernetes cluster network.
Gain access to the Kubernetes cluster network effortlessly using service names or Pod IP/Service IP. Facilitate the
interception of inbound traffic from remote Kubernetes cluster services to your local PC through a service mesh and
more.
For instance, you have the flexibility to run your Kubernetes pod within a local Docker container, ensuring an identical
environment, volume, and network setup.
With KubeVPN, empower yourself to develop applications entirely on your local PC!
![arch](docs/en/images/kubevpn-proxy-tun-arch.svg)
## Content
1. [QuickStart](./README.md#quickstart)
2. [Functions](./README.md#functions)
3. [Architecture](./README.md#architecture)
4. [Contributions](./README.md#Contributions)
## QuickStart
```shell
git clone https://github.com/wencaiwulue/kubevpn.git
cd kubevpn
make kubevpn-linux
make kubevpn-macos
make kubevpn-windows
```
if you are using windows, you can build by this command:
### Install from script ( macOS / Linux)
```shell
go build github.com/wencaiwulue/kubevpn/cmd/kubevpn -o kubevpn.exe
curl -fsSL https://kubevpn.dev/install.sh | sh
```
if you installed Go 1.16+, you can use install it by this command directly:
### Install from [brew](https://brew.sh/) (macOS / Linux)
```shell
go install github.com/wencaiwulue/kubevpn/cmd/kubevpn@latest
brew install kubevpn
```
### Install from [snap](https://snapcraft.io/kubevpn) (Linux)
```shell
sudo snap install kubevpn
```
### Install from [scoop](https://scoop.sh/) (Windows)
```shell
scoop bucket add extras
scoop install kubevpn
```
### Install from [krew](https://krew.sigs.k8s.io/) (Windows / macOS / Linux)
```shell
kubectl krew index add kubevpn https://github.com/kubenetworks/kubevpn.git
kubectl krew install kubevpn/kubevpn
kubectl kubevpn
```
### Install from GitHub release (Windows / macOS / Linux)
[https://github.com/kubenetworks/kubevpn/releases/latest](https://github.com/kubenetworks/kubevpn/releases/latest)
### Install bookinfo as demo application
```shell
kubectl apply -f https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/bookinfo.yaml
kubectl apply -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
```
For clean up after test
```shell
kubectl delete -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
```
## Functions
### Connect to k8s cluster network
use command `kubevpn connect` connect to k8s cluster network, prompt `Password:` need to input computer
password. to enable root operation (create a tun device).
```shell
➜ ~ kubevpn connect
INFO[0000] [sudo kubevpn connect]
Password:
2022/02/05 12:09:22 connect.go:303: kubeconfig path: /Users/naison/.kube/config, namespace: default, services: []
2022/02/05 12:09:28 remote.go:47: traffic manager not exist, try to create it...
2022/02/05 12:09:28 remote.go:121: pod kubevpn.traffic.manager status is Pending
2022/02/05 12:09:29 remote.go:121: pod kubevpn.traffic.manager status is Running
Forwarding from 0.0.0.0:10800 -> 10800
2022/02/05 12:09:31 connect.go:171: port forward ready
2022/02/05 12:09:31 connect.go:193: your ip is 223.254.254.176
2022/02/05 12:09:31 connect.go:197: tunnel connected
Handling connection for 10800
2022/02/05 12:09:31 connect.go:211: dns service ok
Starting connect
Getting network CIDR from cluster info...
Getting network CIDR from CNI...
Getting network CIDR from services...
Labeling Namespace default
Creating ServiceAccount kubevpn-traffic-manager
Creating Roles kubevpn-traffic-manager
Creating RoleBinding kubevpn-traffic-manager
Creating Service kubevpn-traffic-manager
Creating MutatingWebhookConfiguration kubevpn-traffic-manager
Creating Deployment kubevpn-traffic-manager
Pod kubevpn-traffic-manager-66d969fd45-9zlbp is Pending
Container Reason Message
control-plane ContainerCreating
vpn ContainerCreating
webhook ContainerCreating
Pod kubevpn-traffic-manager-66d969fd45-9zlbp is Running
Container Reason Message
control-plane ContainerRunning
vpn ContainerRunning
webhook ContainerRunning
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~
```
already connected to cluster network, use command `kubevpn status` to check status
```shell
➜ ~ kubevpn status
ID Mode Cluster Kubeconfig Namespace Status
0 full ccijorbccotmqodvr189g /Users/naison/.kube/config default Connected
➜ ~
```
use pod `productpage-788df7ff7f-jpkcs` IP `172.29.2.134`
```shell
➜ ~ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
details-7db5668668-mq9qr 1/1 Running 0 7m 172.27.0.199 172.30.0.14 <none> <none>
kubevpn.traffic.manager 1/1 Running 0 74s 172.27.0.207 172.30.0.14 <none> <none>
productpage-8f9d86644-z8snh 1/1 Running 0 6m59s 172.27.0.206 172.30.0.14 <none> <none>
ratings-859b96848d-68d7n 1/1 Running 0 6m59s 172.27.0.201 172.30.0.14 <none> <none>
reviews-dcf754f9d-46l4j 1/1 Running 0 6m59s 172.27.0.202 172.30.0.14 <none> <none>
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
authors-dbb57d856-mbgqk 3/3 Running 0 7d23h 172.29.2.132 192.168.0.5 <none> <none>
details-7d8b5f6bcf-hcl4t 1/1 Running 0 61d 172.29.0.77 192.168.104.255 <none> <none>
kubevpn-traffic-manager-66d969fd45-9zlbp 3/3 Running 0 74s 172.29.2.136 192.168.0.5 <none> <none>
productpage-788df7ff7f-jpkcs 1/1 Running 0 61d 172.29.2.134 192.168.0.5 <none> <none>
ratings-77b6cd4499-zvl6c 1/1 Running 0 61d 172.29.0.86 192.168.104.255 <none> <none>
reviews-85c88894d9-vgkxd 1/1 Running 0 24d 172.29.2.249 192.168.0.5 <none> <none>
```
use `ping` to test connection, seems good
```shell
➜ ~ ping 172.27.0.206
PING 172.27.0.206 (172.27.0.206): 56 data bytes
64 bytes from 172.27.0.206: icmp_seq=0 ttl=63 time=49.563 ms
64 bytes from 172.27.0.206: icmp_seq=1 ttl=63 time=43.014 ms
64 bytes from 172.27.0.206: icmp_seq=2 ttl=63 time=43.841 ms
64 bytes from 172.27.0.206: icmp_seq=3 ttl=63 time=44.004 ms
64 bytes from 172.27.0.206: icmp_seq=4 ttl=63 time=43.484 ms
➜ ~ ping 172.29.2.134
PING 172.29.2.134 (172.29.2.134): 56 data bytes
64 bytes from 172.29.2.134: icmp_seq=0 ttl=63 time=55.727 ms
64 bytes from 172.29.2.134: icmp_seq=1 ttl=63 time=56.270 ms
64 bytes from 172.29.2.134: icmp_seq=2 ttl=63 time=55.228 ms
64 bytes from 172.29.2.134: icmp_seq=3 ttl=63 time=54.293 ms
^C
--- 172.27.0.206 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 43.014/44.781/49.563/2.415 ms
--- 172.29.2.134 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 54.293/55.380/56.270/0.728 ms
```
use service `productpage` IP `172.21.10.49`
```shell
➜ ~ kubectl get services -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
details ClusterIP 172.27.255.92 <none> 9080/TCP 9m7s app=details
productpage ClusterIP 172.27.255.48 <none> 9080/TCP 9m6s app=productpage
ratings ClusterIP 172.27.255.154 <none> 9080/TCP 9m7s app=ratings
reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=reviews
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
authors ClusterIP 172.21.5.160 <none> 9080/TCP 114d app=authors
details ClusterIP 172.21.6.183 <none> 9080/TCP 114d app=details
kubernetes ClusterIP 172.21.0.1 <none> 443/TCP 319d <none>
kubevpn-traffic-manager ClusterIP 172.21.2.86 <none> 8422/UDP,10800/TCP,9002/TCP,80/TCP 2m28s app=kubevpn-traffic-manager
productpage ClusterIP 172.21.10.49 <none> 9080/TCP 114d app=productpage
ratings ClusterIP 172.21.3.247 <none> 9080/TCP 114d app=ratings
reviews ClusterIP 172.21.8.24 <none> 9080/TCP 114d app=reviews
```
use command `curl` to test service connection
```shell
➜ ~ curl 172.27.255.48:9080
➜ ~ curl 172.21.10.49:9080
<!DOCTYPE html>
<html>
<head>
@@ -97,8 +208,18 @@ reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=
<meta name="viewport" content="width=device-width, initial-scale=1">
```
seems good too~
### Domain resolve
support k8s dns name resolve.
a Pod/Service named `productpage` in the `default` namespace can successfully resolve by following name:
- `productpage`
- `productpage.default`
- `productpage.default.svc.cluster.local`
```shell
➜ ~ curl productpage.default.svc.cluster.local:9080
<!DOCTYPE html>
@@ -112,6 +233,9 @@ reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=
### Short domain resolve
To access the service in the cluster, service name or you can use the short domain name, such
as `productpage`
```shell
➜ ~ curl productpage:9080
<!DOCTYPE html>
@@ -123,31 +247,73 @@ reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=
...
```
### Reverse proxy
***Disclaimer:*** This only works on the namespace where kubevpn-traffic-manager is deployed. Otherwise,
use [Domain resolve](./README.md#domain-resolve)
### Connect to multiple kubernetes cluster network
- Mode `lite`: can connect to multiple cluster network, design for only connecting to multiple cluster network.
- Mode `Full`: not only connect to cluster network, it also supports proxy workloads inbound traffic to local PC.
already connected cluster `ccijorbccotmqodvr189g` with mode `full`
```shell
➜ ~ kubevpn connect --workloads=service/productpage
INFO[0000] [sudo kubevpn connect --workloads=service/productpage]
Password:
2022/02/05 12:18:22 connect.go:303: kubeconfig path: /Users/naison/.kube/config, namespace: default, services: [service/productpage]
2022/02/05 12:18:28 remote.go:47: traffic manager not exist, try to create it...
2022/02/05 12:18:28 remote.go:121: pod kubevpn.traffic.manager status is Pending
2022/02/05 12:18:29 remote.go:121: pod kubevpn.traffic.manager status is Running
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
deployment "productpage" successfully rolled out
Forwarding from 0.0.0.0:10800 -> 10800
2022/02/05 12:18:34 connect.go:171: port forward ready
2022/02/05 12:18:34 connect.go:193: your ip is 223.254.254.176
2022/02/05 12:18:34 connect.go:197: tunnel connected
Handling connection for 10800
2022/02/05 12:18:35 connect.go:211: dns service ok
➜ ~ kubevpn status
ID Mode Cluster Kubeconfig Namespace Status
0 full ccijorbccotmqodvr189g /Users/naison/.kube/config default Connected
```
then connect to another cluster `ccidd77aam2dtnc3qnddg` with mode `lite`
```shell
➜ ~ kubevpn connect -n default --kubeconfig ~/.kube/dev_config --lite
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
```
use command `kubevpn status` to check connection status
```shell
➜ ~ kubevpn status
ID Mode Cluster Kubeconfig Namespace Status
0 full ccijorbccotmqodvr189g /Users/naison/.kube/config default Connected
1 lite ccidd77aam2dtnc3qnddg /Users/naison/.kube/dev_config default Connected
➜ ~
```
### Reverse proxy
use command `kubevpn proxy` to proxy all inbound traffic to local computer.
```shell
➜ ~ kubevpn proxy deployment/productpage
Connected to cluster
Injecting inbound sidecar for deployment/productpage
Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployment/productpage
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~
```
For local testing, save the following code as `hello.go`
```go
package main
import (
"fmt"
"io"
"net/http"
)
@@ -155,11 +321,56 @@ import (
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
_, _ = io.WriteString(writer, "Hello world!")
fmt.Printf(">>Received request: %s %s from %s\n", request.Method, request.RequestURI, request.RemoteAddr)
})
_ = http.ListenAndServe(":8080", nil)
_ = http.ListenAndServe(":9080", nil)
}
```
and compile it
```
go build hello.go
```
then run it
```
./hello &
```
```shell
export selector=productpage
export pod=`kubectl get pods -l app=${selector} -n default -o jsonpath='{.items[0].metadata.name}'`
export pod_ip=`kubectl get pod $pod -n default -o jsonpath='{.status.podIP}'`
curl -v -H "foo: bar" http://$pod_ip:9080/health
```
response would like below
```
curl -v -H "foo: bar" http://$pod_ip:9080/health
* Trying 192.168.72.77:9080...
* Connected to 192.168.72.77 (192.168.72.77) port 9080 (#0)
> GET /health HTTP/1.1
> Host: 192.168.72.77:9080
> User-Agent: curl/7.87.0
> Accept: */*
> foo: bar
>
>>Received request: GET /health from xxx.xxx.xxx.xxx:52974
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sat, 04 Nov 2023 10:19:50 GMT
< Content-Length: 12
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 192.168.72.77 left intact
Hello world!
```
also you can access via service name
```shell
➜ ~ curl productpage:9080
Hello world!%
@@ -169,26 +380,24 @@ Hello world!%
### Reverse proxy with mesh
Only support HTTP and GRPC, with specific header `"a: 1"` will route to your local machine
Support HTTP, GRPC and WebSocket etc. with specific header `"foo: bar"` will route to your local machine
```shell
➜ ~ kubevpn connect --workloads=service/productpage --mode=mesh --headers a=1
INFO[0000] [sudo kubevpn connect --workloads=service/productpage --mode=mesh --headers a=1]
2022/02/05 12:22:28 connect.go:303: kubeconfig path: /Users/naison/.kube/config, namespace: default, services: [service/productpage]
2022/02/05 12:22:34 remote.go:47: traffic manager not exist, try to create it...
2022/02/05 12:22:34 remote.go:121: pod kubevpn.traffic.manager status is Pending
2022/02/05 12:22:36 remote.go:121: pod kubevpn.traffic.manager status is Running
➜ ~ kubevpn proxy deployment/productpage --headers foo=bar
Connected to cluster
Injecting inbound sidecar for deployment/productpage
Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
deployment "productpage" successfully rolled out
Forwarding from 0.0.0.0:10800 -> 10800
2022/02/05 12:22:43 connect.go:171: port forward ready
2022/02/05 12:22:43 connect.go:193: your ip is 223.254.254.176
2022/02/05 12:22:43 connect.go:197: tunnel connected
Handling connection for 10800
2022/02/05 12:22:43 connect.go:211: dns service ok
Rollout successfully for deployment/productpage
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~
```
first access without header "foo: bar", it will access existing pod on kubernetes cluster.
```shell
➜ ~ curl productpage:9080
<!DOCTYPE html>
@@ -201,17 +410,313 @@ Handling connection for 10800
...
```
Now let's access local service with header `"foo: bar"`
```shell
➜ ~ curl productpage:9080 -H "a: 1"
Hello world!%
➜ ~ curl productpage:9080 -H "foo: bar"
>>Received request: GET / from xxx.xxx.xxx.xxx:51296
Hello world!
```
If you want to cancel proxy, just run command:
```shell
➜ ~ kubevpn leave deployments/productpage
Leaving workload deployments/productpage
Checking rollout status for deployments/productpage
Waiting for deployment "productpage" rollout to finish: 0 out of 1 new replicas have been updated...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployments/productpage
```
### Dev mode in local Docker 🐳
Run the Kubernetes pod in the local Docker container, and cooperate with the service mesh to intercept the traffic with
the specified header to the local, or all the traffic to the local.
```shell
➜ ~ kubevpn dev deployment/authors --headers foo=bar --entrypoint sh
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
Injecting inbound sidecar for deployment/authors
Patching workload deployment/authors
Checking rollout status for deployment/authors
Waiting for deployment "authors" rollout to finish: 0 out of 1 new replicas have been updated...
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
deployment "authors" successfully rolled out
Rollout successfully for Deployment.apps/authors
tar: removing leading '/' from member names
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/4563987760170736212:/var/run/secrets/kubernetes.io/serviceaccount
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/4044542168121221027:/var/run/secrets/kubernetes.io/serviceaccount
create docker network 56c25058d4b7498d02c2c2386ccd1b2b127cb02e8a1918d6d24bffd18570200e
Created container: nginx_default_kubevpn_a9a22
Wait container nginx_default_kubevpn_a9a22 to be running...
Container nginx_default_kubevpn_a9a22 is running on port 80/tcp:80 8888/tcp:8888 9080/tcp:9080 now
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Created main container: authors_default_kubevpn_a9a22
/opt/microservices # ls
app
/opt/microservices # ps -ef
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx -g daemon off;
29 101 0:00 nginx: worker process
30 101 0:00 nginx: worker process
31 101 0:00 nginx: worker process
32 101 0:00 nginx: worker process
33 101 0:00 nginx: worker process
34 root 0:00 {sh} /usr/bin/qemu-x86_64 /bin/sh sh
44 root 0:00 ps -ef
/opt/microservices # apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/4) Installing brotli-libs (1.0.9-r5)
(2/4) Installing nghttp2-libs (1.43.0-r0)
(3/4) Installing libcurl (8.0.1-r0)
(4/4) Installing curl (8.0.1-r0)
Executing busybox-1.33.1-r3.trigger
OK: 8 MiB in 19 packages
/opt/microservices # ./app &
/opt/microservices # 2023/09/30 13:41:58 Start listening http port 9080 ...
/opt/microservices # curl localhost:9080/health
{"status":"Authors is healthy"} /opt/microservices # echo "continue testing pod access..."
continue testing pod access...
/opt/microservices # exit
Created container: default_authors
Wait container default_authors to be running...
Container default_authors is running now
Disconnecting from the cluster...
Leaving workload deployments.apps/authors
Disconnecting from the cluster...
Performing cleanup operations
Clearing DNS settings
➜ ~
```
You can see that it will start up two containers with docker, mapping to pod two container, and share port with same
network, you can use `localhost:port`
to access another container. And more, all environment、volume and network are the same as remote kubernetes pod, it is
truly consistent with the kubernetes runtime. Makes develop on local PC come true.
```shell
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afdecf41c08d naison/authors:latest "sh" 37 seconds ago Up 36 seconds authors_default_kubevpn_a9a22
fc04e42799a5 nginx:latest "/docker-entrypoint.…" 37 seconds ago Up 37 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:8888->8888/tcp, 0.0.0.0:9080->9080/tcp nginx_default_kubevpn_a9a22
➜ ~
```
Here is how to access pod in local docker container
```shell
export authors_pod=`kubectl get pods -l app=authors -n default -o jsonpath='{.items[0].metadata.name}'`
export authors_pod_ip=`kubectl get pod $authors_pod -n default -o jsonpath='{.status.podIP}'`
curl -kv -H "foo: bar" http://$authors_pod_ip:80/health
```
Verify logs of nginx container
```shell
docker logs $(docker ps --format '{{.Names}}' | grep nginx_default_kubevpn)
```
If you just want to start up a docker image, you can use a simple way like this:
```shell
kubevpn dev deployment/authors --no-proxy
```
Example
```shell
➜ ~ kubevpn dev deployment/authors --no-proxy
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
tar: removing leading '/' from member names
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/5631078868924498209:/var/run/secrets/kubernetes.io/serviceaccount
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/1548572512863475037:/var/run/secrets/kubernetes.io/serviceaccount
create docker network 56c25058d4b7498d02c2c2386ccd1b2b127cb02e8a1918d6d24bffd18570200e
Created container: nginx_default_kubevpn_ff34b
Wait container nginx_default_kubevpn_ff34b to be running...
Container nginx_default_kubevpn_ff34b is running on port 80/tcp:80 8888/tcp:8888 9080/tcp:9080 now
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Created main container: authors_default_kubevpn_ff34b
2023/09/30 14:02:31 Start listening http port 9080 ...
```
Now the main process will hang up to show you log.
If you want to specify the image to start the container locally, you can use the parameter `--dev-image`. When the
image does not exist locally, it will be pulled from the corresponding mirror warehouse. If you want to specify startup
parameters, you can use `--entrypoint` parameter, replace it with the command you want to execute, such
as `--entrypoint /bin/bash`, for more parameters, see `kubevpn dev --help`.
### DinD ( Docker in Docker ) use kubevpn in Docker
If you want to start the development mode locally using Docker in Docker (DinD), because the program will read and
write the `/tmp` directory, you need to manually add the parameter `-v /tmp:/tmp` (outer docker) and another thing is
you
need to special parameter `--network` (inner docker) for sharing network and pid
Example:
```shell
docker run -it --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v ~/.kube/config:/root/.kube/config --platform linux/amd64 ghcr.io/kubenetworks/kubevpn:latest
```
```shell
➜ ~ docker run -it --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v ~/.kube/vke:/root/.kube/config --platform linux/amd64 ghcr.io/kubenetworks/kubevpn:latest
Unable to find image 'ghcr.io/kubenetworks/kubevpn:latest' locally
latest: Pulling from ghcr.io/kubenetworks/kubevpn
9c704ecd0c69: Already exists
4987d0a976b5: Pull complete
8aa94c4fc048: Pull complete
526fee014382: Pull complete
6c1c2bedceb6: Pull complete
97ac845120c5: Pull complete
ca82aef6a9eb: Pull complete
1fd9534c7596: Pull complete
588bd802eb9c: Pull complete
Digest: sha256:368db2e0d98f6866dcefd60512960ce1310e85c24a398fea2a347905ced9507d
Status: Downloaded newer image for ghcr.io/kubenetworks/kubevpn:latest
WARNING: image with reference ghcr.io/kubenetworks/kubevpn was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64
root@5732124e6447:/app# kubevpn dev deployment/authors --headers user=naison --entrypoint sh
hostname is 5732124e6447
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
Injecting inbound sidecar for deployment/authors
Patching workload deployment/authors
Checking rollout status for deployment/authors
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
deployment "authors" successfully rolled out
Rollout successfully for Deployment.apps/authors
tar: removing leading '/' from member names
/tmp/6460902982794789917:/var/run/secrets/kubernetes.io/serviceaccount
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
/tmp/5028895788722532426:/var/run/secrets/kubernetes.io/serviceaccount
Network mode is container:d0b3dab8912a
Created container: nginx_default_kubevpn_6df63
Wait container nginx_default_kubevpn_6df63 to be running...
Container nginx_default_kubevpn_6df63 is running now
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Created main container: authors_default_kubevpn_6df5f
/opt/microservices # ps -ef
PID USER TIME COMMAND
1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash
14 root 0:02 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn kubevpn dev deployment/authors --headers
25 root 0:01 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon
37 root 0:04 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon --sudo
53 root 0:00 nginx: master process nginx -g daemon off;
(4/4) Installing curl (8.0.1-r0)
Executing busybox-1.33.1-r3.trigger
OK: 8 MiB in 19 packagesnx: worker process
/opt/microservices #
/opt/microservices # cat > hello.go <<EOF
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
_, _ = io.WriteString(writer, "Hello world!")
fmt.Println(">> Container Received request: %s %s from %s\n", request.Method, request.RequestURI, request.RemoteAddr)
})
fmt.Println("Start listening http port 9080 ...")
_ = http.ListenAndServe(":9080", nil)
}
EOF
/opt/microservices # go build hello.go
/opt/microservices #
//opt/microservices # ls -alh
total 12M
drwxr-xr-x 1 root root 26 Nov 4 10:29 .
drwxr-xr-x 1 root root 26 Oct 18 2021 ..
-rwxr-xr-x 1 root root 6.3M Oct 18 2021 app
-rwxr-xr-x 1 root root 5.8M Nov 4 10:29 hello
-rw-r--r-- 1 root root 387 Nov 4 10:28 hello.go
/opt/microservices #
/opt/microservices # apk add curl
OK: 8 MiB in 19 packages
/opt/microservices # ./hello &
/opt/microservices # Start listening http port 9080 ...
[2]+ Done ./hello
/opt/microservices # curl localhost:9080
>> Container Received request: GET / from 127.0.0.1:41230
Hello world!/opt/microservices #
/opt/microservices # curl authors:9080/health -H "foo: bar"
>>Received request: GET /health from 198.19.0.109:57930
Hello world!/opt/microservices #
/opt/microservices # curl localhost:9080/health
{"status":"Authors is healthy"}/opt/microservices # exit
Created container: default_authors
Wait container default_authors to be running...
Container default_authors is running now
Disconnecting from the cluster...
Leaving workload deployments.apps/authors
Disconnecting from the cluster...
Performing cleanup operations
Clearing DNS settings
root@d0b3dab8912a:/app# exit
exit
➜ ~
```
during test, check what container is running
```text
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1cd576b51b66 naison/authors:latest "sh" 4 minutes ago Up 4 minutes authors_default_kubevpn_6df5f
56a6793df82d nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes nginx_default_kubevpn_6df63
d0b3dab8912a ghcr.io/kubenetworks/kubevpn:v2.0.0 "/bin/bash" 5 minutes ago Up 5 minutes upbeat_noyce
➜ ~
```
* For clean up after test
```shell
kubectl delete -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
```
### Multiple Protocol
support OSI model layers 3 and above, protocols like `ICMP`, `TCP`, and `UDP`...
- TCP
- UDP
- HTTP
- ICMP
- gRPC
- Thrift
- WebSocket
- HTTP
- ...
### Cross-platform
@@ -220,6 +725,21 @@ Hello world!%
- Linux
- Windows
on Windows platform, you need to
install [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.2)
in advance
## Architecture
[architecture](https://kubevpn.dev/docs/architecture/connect).
## Contributions
Always welcome. Just opening an issue should be also grateful.
If you want to debug this project on local PC. Please follow the steps bellow:
- Startup daemon and sudo daemon process with IDE debug mode. (Essentially two GRPC server)
- Add breakpoint to file `pkg/daemon/action/connect.go:21`.
- Open another terminal run `make kubevpn`.
- Then run `./bin/kubevpn connect` and it will hit breakpoint.
### Supported by
[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://jb.gg/OpenSourceSupport)

View File

@@ -1,92 +1,182 @@
![kubevpn](https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/flat_log.png)
[![GitHub Workflow][1]](https://github.com/kubenetworks/kubevpn/actions)
[![Go Version][2]](https://github.com/kubenetworks/kubevpn/blob/master/go.mod)
[![Go Report][3]](https://goreportcard.com/report/github.com/wencaiwulue/kubevpn)
[![Maintainability][4]](https://codeclimate.com/github/kubenetworks/kubevpn/maintainability)
[![GitHub License][5]](https://github.com/kubenetworks/kubevpn/blob/main/LICENSE)
[![Docker Pulls][6]](https://hub.docker.com/r/naison/kubevpn)
[![Releases][7]](https://github.com/kubenetworks/kubevpn/releases)
[![GoDoc](https://godoc.org/github.com/kubenetworks/kubevpn?status.png)](https://pkg.go.dev/github.com/wencaiwulue/kubevpn/v2)
[![codecov](https://codecov.io/gh/wencaiwulue/kubevpn/graph/badge.svg?token=KMDSINSDEP)](https://codecov.io/gh/wencaiwulue/kubevpn)
[![Snapcraft](https://snapcraft.io/kubevpn/badge.svg)](https://snapcraft.io/kubevpn)
[1]: https://img.shields.io/github/actions/workflow/status/kubenetworks/kubevpn/release.yml?logo=github
[2]: https://img.shields.io/github/go-mod/go-version/kubenetworks/kubevpn?logo=go
[3]: https://goreportcard.com/badge/github.com/wencaiwulue/kubevpn?style=flat
[4]: https://api.codeclimate.com/v1/badges/b5b30239174fc6603aca/maintainability
[5]: https://img.shields.io/github/license/kubenetworks/kubevpn
[6]: https://img.shields.io/docker/pulls/naison/kubevpn?logo=docker
[7]: https://img.shields.io/github/v/release/kubenetworks/kubevpn?logo=smartthings
# KubeVPN
[English](README.md) | [中文](README_ZH.md) | [维基](https://github.com/wencaiwulue/kubevpn/wiki/%E6%9E%B6%E6%9E%84)
[English](README.md) | [中文](README_ZH.md) | [维基](https://github.com/kubenetworks/kubevpn/wiki/%E6%9E%B6%E6%9E%84)
一个本地连接云端 kubernetes 网络的工具,可以在本地直接访问远端集群的服务。也可以在远端集群访问到本地服务,便于调试及开发
KubeVPN 提供一个云原生开发环境。通过连接云端 kubernetes 网络,可以在本地使用 k8s dns 或者 Pod IP / Service IP
直接访问远端集群中的服务。拦截远端集群中的工作负载的入流量到本地电脑,配合服务网格便于调试及开发。同时还可以使用开发模式,直接在本地使用
Docker
模拟 k8s pod runtime 将容器运行在本地 (具有相同的环境变量,磁盘和网络)。
![架构](docs/en/images/kubevpn-proxy-tun-arch.svg)
## 内容
1. [快速开始](./README_ZH.md#快速开始)
2. [功能](./README_ZH.md#功能)
3. [架构](./README_ZH.md#架构)
4. [贡献代码](./README_ZH.md#贡献代码)
## 快速开始
```shell
git clone https://github.com/wencaiwulue/kubevpn.git
cd kubevpn
make kubevpn-linux
make kubevpn-macos
make kubevpn-windows
```
如果你在使用 Windows 系统,可以使用下面这条命令构建:
### 使用脚本安装 ( macOS / Linux)
```shell
go build github.com/wencaiwulue/kubevpn/cmd/kubevpn -o kubevpn.exe
curl -fsSL https://kubevpn.dev/install.sh | sh
```
如果安装了 Go 1.16 及以上版本,可以使用如下命令安装:
### 使用 [brew](https://brew.sh/) 安装 (macOS / Linux)
```shell
go install github.com/wencaiwulue/kubevpn/cmd/kubevpn@latest
brew install kubevpn
```
### 使用 [snap](https://snapcraft.io/kubevpn) 安装 (Linux)
```shell
sudo snap install kubevpn
```
### 使用 [scoop](https://scoop.sh/) (Windows)
```shell
scoop bucket add extras
scoop install kubevpn
```
### 使用 [krew](https://krew.sigs.k8s.io/) (Windows / macOS / Linux)
```shell
kubectl krew index add kubevpn https://github.com/kubenetworks/kubevpn.git
kubectl krew install kubevpn/kubevpn
kubectl kubevpn
```
### 从 Github release 下载 (Windows / macOS / Linux)
[https://github.com/kubenetworks/kubevpn/releases/latest](https://github.com/kubenetworks/kubevpn/releases/latest)
### 安装 bookinfo 作为 demo 应用
```shell
kubectl apply -f https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/bookinfo.yaml
kubectl apply -f https://raw.githubusercontent.com/kubenetworks/kubevpn/master/samples/bookinfo.yaml
```
## 功能
### 链接到集群网络
使用命令 `kubevpn connect` 链接到集群,请注意这里需要输入电脑密码。因为需要 `root` 权限。(创建虚拟网卡)
```shell
➜ ~ kubevpn connect
INFO[0000] [sudo kubevpn connect]
Password:
2022/02/05 12:09:22 connect.go:303: kubeconfig path: /Users/naison/.kube/config, namespace: default, services: []
2022/02/05 12:09:28 remote.go:47: traffic manager not exist, try to create it...
2022/02/05 12:09:28 remote.go:121: pod kubevpn.traffic.manager status is Pending
2022/02/05 12:09:29 remote.go:121: pod kubevpn.traffic.manager status is Running
Forwarding from 0.0.0.0:10800 -> 10800
2022/02/05 12:09:31 connect.go:171: port forward ready
2022/02/05 12:09:31 connect.go:193: your ip is 223.254.254.176
2022/02/05 12:09:31 connect.go:197: tunnel connected
Handling connection for 10800
2022/02/05 12:09:31 connect.go:211: dns service ok
Starting connect
Getting network CIDR from cluster info...
Getting network CIDR from CNI...
Getting network CIDR from services...
Labeling Namespace default
Creating ServiceAccount kubevpn-traffic-manager
Creating Roles kubevpn-traffic-manager
Creating RoleBinding kubevpn-traffic-manager
Creating Service kubevpn-traffic-manager
Creating MutatingWebhookConfiguration kubevpn-traffic-manager
Creating Deployment kubevpn-traffic-manager
Pod kubevpn-traffic-manager-66d969fd45-9zlbp is Pending
Container Reason Message
control-plane ContainerCreating
vpn ContainerCreating
webhook ContainerCreating
Pod kubevpn-traffic-manager-66d969fd45-9zlbp is Running
Container Reason Message
control-plane ContainerRunning
vpn ContainerRunning
webhook ContainerRunning
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~
```
提示已经链接到集群了。使用命令 `kubevpn status` 检查一下状态。
```shell
➜ ~ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
details-7db5668668-mq9qr 1/1 Running 0 7m 172.27.0.199 172.30.0.14 <none> <none>
kubevpn.traffic.manager 1/1 Running 0 74s 172.27.0.207 172.30.0.14 <none> <none>
productpage-8f9d86644-z8snh 1/1 Running 0 6m59s 172.27.0.206 172.30.0.14 <none> <none>
ratings-859b96848d-68d7n 1/1 Running 0 6m59s 172.27.0.201 172.30.0.14 <none> <none>
reviews-dcf754f9d-46l4j 1/1 Running 0 6m59s 172.27.0.202 172.30.0.14 <none> <none>
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
authors-dbb57d856-mbgqk 3/3 Running 0 7d23h 172.29.2.132 192.168.0.5 <none> <none>
details-7d8b5f6bcf-hcl4t 1/1 Running 0 61d 172.29.0.77 192.168.104.255 <none> <none>
kubevpn-traffic-manager-66d969fd45-9zlbp 3/3 Running 0 74s 172.29.2.136 192.168.0.5 <none> <none>
productpage-788df7ff7f-jpkcs 1/1 Running 0 61d 172.29.2.134 192.168.0.5 <none> <none>
ratings-77b6cd4499-zvl6c 1/1 Running 0 61d 172.29.0.86 192.168.104.255 <none> <none>
reviews-85c88894d9-vgkxd 1/1 Running 0 24d 172.29.2.249 192.168.0.5 <none> <none>
```
找一个 pod 的 IP比如 `productpage-788df7ff7f-jpkcs` 的 IP `172.29.2.134`
```shell
➜ ~ ping 172.27.0.206
PING 172.27.0.206 (172.27.0.206): 56 data bytes
64 bytes from 172.27.0.206: icmp_seq=0 ttl=63 time=49.563 ms
64 bytes from 172.27.0.206: icmp_seq=1 ttl=63 time=43.014 ms
64 bytes from 172.27.0.206: icmp_seq=2 ttl=63 time=43.841 ms
64 bytes from 172.27.0.206: icmp_seq=3 ttl=63 time=44.004 ms
64 bytes from 172.27.0.206: icmp_seq=4 ttl=63 time=43.484 ms
➜ ~ ping 172.29.2.134
PING 172.29.2.134 (172.29.2.134): 56 data bytes
64 bytes from 172.29.2.134: icmp_seq=0 ttl=63 time=55.727 ms
64 bytes from 172.29.2.134: icmp_seq=1 ttl=63 time=56.270 ms
64 bytes from 172.29.2.134: icmp_seq=2 ttl=63 time=55.228 ms
64 bytes from 172.29.2.134: icmp_seq=3 ttl=63 time=54.293 ms
^C
--- 172.27.0.206 ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 43.014/44.781/49.563/2.415 ms
--- 172.29.2.134 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 54.293/55.380/56.270/0.728 ms
```
测试应该可以直接 Ping 通,说明本地可以正常访问到集群网络了。
```shell
➜ ~ kubectl get services -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
details ClusterIP 172.27.255.92 <none> 9080/TCP 9m7s app=details
productpage ClusterIP 172.27.255.48 <none> 9080/TCP 9m6s app=productpage
ratings ClusterIP 172.27.255.154 <none> 9080/TCP 9m7s app=ratings
reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=reviews
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
authors ClusterIP 172.21.5.160 <none> 9080/TCP 114d app=authors
details ClusterIP 172.21.6.183 <none> 9080/TCP 114d app=details
kubernetes ClusterIP 172.21.0.1 <none> 443/TCP 319d <none>
kubevpn-traffic-manager ClusterIP 172.21.2.86 <none> 8422/UDP,10800/TCP,9002/TCP,80/TCP 2m28s app=kubevpn-traffic-manager
productpage ClusterIP 172.21.10.49 <none> 9080/TCP 114d app=productpage
ratings ClusterIP 172.21.3.247 <none> 9080/TCP 114d app=ratings
reviews ClusterIP 172.21.8.24 <none> 9080/TCP 114d app=reviews
```
找一个 service 的 IP比如 `productpage` 的 IP `172.21.10.49`,试着访问一下服务 `productpage`
```shell
➜ ~ curl 172.27.255.48:9080
➜ ~ curl 172.21.10.49:9080
<!DOCTYPE html>
<html>
<head>
@@ -96,8 +186,16 @@ reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=
<meta name="viewport" content="width=device-width, initial-scale=1">
```
可以看到也可以正常访问,也就是可以在本地访问到集群的 pod 和 service 了~
### 域名解析功能
支持 k8s dns 解析。比如一个名为 `productpage` 的 Pod 或者 Service 处于 `default` 命名空间下可以被如下域名正常解析到:
- `productpage`
- `productpage.default`
- `productpage.default.svc.cluster.local`
```shell
➜ ~ curl productpage.default.svc.cluster.local:9080
<!DOCTYPE html>
@@ -109,8 +207,15 @@ reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=
<meta name="viewport" content="width=device-width, initial-scale=1">
```
可以看到能够被正常解析,并且返回相应内容。
### 短域名解析功能
连接到此命名空间下,可以直接使用 `service` name 的方式访问,否则访问其它命令空间下的服务,需要带上命令空间作为域名的一部分,使用如下的域名即可。
- `productpage.default`
- `productpage.default.svc.cluster.local`
```shell
➜ ~ curl productpage:9080
<!DOCTYPE html>
@@ -122,27 +227,71 @@ reviews ClusterIP 172.27.255.155 <none> 9080/TCP 9m6s app=
...
```
### 反向代理
可以看到直接使用 service name 的方式,可以正常访问到集群资源。
### 链接到多集群网络
有个两个模式
- 模式 `lite`: 可以链接到多个集群网络,但是仅支持链接到多集群。
- 模式 `full`: 不仅支持链接到单个集群网络,还可以拦截工作负载流量到本地电脑。
可以看到已经链接到了一个集群 `ccijorbccotmqodvr189g`,是 `full` 模式
```shell
➜ ~ kubevpn connect --workloads=service/productpage
INFO[0000] [sudo kubevpn connect --workloads=service/productpage]
Password:
2022/02/05 12:18:22 connect.go:303: kubeconfig path: /Users/naison/.kube/config, namespace: default, services: [service/productpage]
2022/02/05 12:18:28 remote.go:47: traffic manager not exist, try to create it...
2022/02/05 12:18:28 remote.go:121: pod kubevpn.traffic.manager status is Pending
2022/02/05 12:18:29 remote.go:121: pod kubevpn.traffic.manager status is Running
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
deployment "productpage" successfully rolled out
Forwarding from 0.0.0.0:10800 -> 10800
2022/02/05 12:18:34 connect.go:171: port forward ready
2022/02/05 12:18:34 connect.go:193: your ip is 223.254.254.176
2022/02/05 12:18:34 connect.go:197: tunnel connected
Handling connection for 10800
2022/02/05 12:18:35 connect.go:211: dns service ok
➜ ~ kubevpn status
ID Mode Cluster Kubeconfig Namespace Status
0 full ccijorbccotmqodvr189g /Users/naison/.kube/config default Connected
```
此时还可以使用 `lite` 模式链接到其它集群
```shell
➜ ~ kubevpn connect -n default --kubeconfig ~/.kube/dev_config --lite
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
```
使用命令 `kubevpn status` 查看当前链接状态。
```shell
➜ ~ kubevpn status
ID Mode Cluster Kubeconfig Namespace Status
0 full ccijorbccotmqodvr189g /Users/naison/.kube/config default Connected
1 lite ccidd77aam2dtnc3qnddg /Users/naison/.kube/dev_config default Connected
➜ ~
```
可以看到连接到了多个集群。
### 反向代理
使用命令 `kubevpn proxy` 代理所有的入站流量到本地电脑。
```shell
➜ ~ kubevpn proxy deployment/productpage
Connected to cluster
Injecting inbound sidecar for deployment/productpage
Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployment/productpage
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~
```
此时在本地使用 `go` 启动一个服务,用于承接流量。
```go
package main
@@ -159,6 +308,8 @@ func main() {
}
```
使用 `service` name 的方式,直接访问集群中的 `productpage` 服务。
```shell
➜ ~ curl productpage:9080
Hello world!%
@@ -166,28 +317,28 @@ Hello world!%
Hello world!%
```
可以看到直接击中了本地电脑的服务。
### 反向代理支持 service mesh
支持 HTTP GRPC, 携带了指定 header `"a: 1"` 的流量,将会路由到本地
支持 HTTP, GRPC 和 WebSocket 等, 携带了指定 header `"foo: bar"` 的流量,将会路由到本地
```shell
➜ ~ kubevpn connect --workloads=service/productpage --mode=mesh --headers a=1
INFO[0000] [sudo kubevpn connect --workloads=service/productpage --mode=mesh --headers a=1]
2022/02/05 12:22:28 connect.go:303: kubeconfig path: /Users/naison/.kube/config, namespace: default, services: [service/productpage]
2022/02/05 12:22:34 remote.go:47: traffic manager not exist, try to create it...
2022/02/05 12:22:34 remote.go:121: pod kubevpn.traffic.manager status is Pending
2022/02/05 12:22:36 remote.go:121: pod kubevpn.traffic.manager status is Running
➜ ~ kubevpn proxy deployment/productpage --headers foo=bar
Connected to cluster
Injecting inbound sidecar for deployment/productpage
Checking rollout status for deployment/productpage
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
deployment "productpage" successfully rolled out
Forwarding from 0.0.0.0:10800 -> 10800
2022/02/05 12:22:43 connect.go:171: port forward ready
2022/02/05 12:22:43 connect.go:193: your ip is 223.254.254.176
2022/02/05 12:22:43 connect.go:197: tunnel connected
Handling connection for 10800
2022/02/05 12:22:43 connect.go:211: dns service ok
Rollout successfully for deployment/productpage
+----------------------------------------------------------+
| Now you can access resources in the kubernetes cluster ! |
+----------------------------------------------------------+
➜ ~
```
不带 header 直接访问集群资源,可以看到返回的是集群中的服务内容。
```shell
➜ ~ curl productpage:9080
<!DOCTYPE html>
@@ -200,17 +351,289 @@ Handling connection for 10800
...
```
带上特定 header 访问集群资源,可以看到返回了本地服务的内容。
```shell
➜ ~ curl productpage:9080 -H "a: 1"
➜ ~ curl productpage:9080 -H "foo: bar"
Hello world!%
```
如果你需要取消代理流量,可以执行如下命令:
```shell
➜ ~ kubevpn leave deployments/productpage
Leaving workload deployments/productpage
Checking rollout status for deployments/productpage
Waiting for deployment "productpage" rollout to finish: 0 out of 1 new replicas have been updated...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "productpage" rollout to finish: 1 old replicas are pending termination...
Rollout successfully for deployments/productpage
```
### 本地进入开发模式 🐳
将 Kubernetes pod 运行在本地的 Docker 容器中,同时配合 service mesh, 拦截带有指定 header 的流量到本地,或者所有的流量到本地。这个开发模式依赖于本地
Docker。
```shell
➜ ~ kubevpn dev deployment/authors --headers foo=bar --entrypoint sh
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
Injecting inbound sidecar for deployment/authors
Patching workload deployment/authors
Checking rollout status for deployment/authors
Waiting for deployment "authors" rollout to finish: 0 out of 1 new replicas have been updated...
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
deployment "authors" successfully rolled out
Rollout successfully for Deployment.apps/authors
tar: removing leading '/' from member names
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/4563987760170736212:/var/run/secrets/kubernetes.io/serviceaccount
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/4044542168121221027:/var/run/secrets/kubernetes.io/serviceaccount
create docker network 56c25058d4b7498d02c2c2386ccd1b2b127cb02e8a1918d6d24bffd18570200e
Created container: nginx_default_kubevpn_a9a22
Wait container nginx_default_kubevpn_a9a22 to be running...
Container nginx_default_kubevpn_a9a22 is running on port 80/tcp:80 8888/tcp:8888 9080/tcp:9080 now
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Created main container: authors_default_kubevpn_a9a22
/opt/microservices # ls
app
/opt/microservices # ps -ef
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx -g daemon off;
29 101 0:00 nginx: worker process
30 101 0:00 nginx: worker process
31 101 0:00 nginx: worker process
32 101 0:00 nginx: worker process
33 101 0:00 nginx: worker process
34 root 0:00 {sh} /usr/bin/qemu-x86_64 /bin/sh sh
44 root 0:00 ps -ef
/opt/microservices # apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/4) Installing brotli-libs (1.0.9-r5)
(2/4) Installing nghttp2-libs (1.43.0-r0)
(3/4) Installing libcurl (8.0.1-r0)
(4/4) Installing curl (8.0.1-r0)
Executing busybox-1.33.1-r3.trigger
OK: 8 MiB in 19 packages
/opt/microservices # ./app &
/opt/microservices # 2023/09/30 13:41:58 Start listening http port 9080 ...
/opt/microservices # curl localhost:9080/health
{"status":"Authors is healthy"} /opt/microservices # echo "continue testing pod access..."
continue testing pod access...
/opt/microservices # exit
Created container: default_authors
Wait container default_authors to be running...
Container default_authors is running now
Disconnecting from the cluster...
Leaving workload deployments.apps/authors
Disconnecting from the cluster...
Performing cleanup operations
Clearing DNS settings
➜ ~
```
此时本地会启动两个 container, 对应 pod 容器中的两个 container, 并且共享端口, 可以直接使用 localhost:port 的形式直接访问另一个
container,
并且, 所有的环境变量、挂载卷、网络条件都和 pod 一样, 真正做到与 kubernetes 运行环境一致。
```shell
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afdecf41c08d naison/authors:latest "sh" 37 seconds ago Up 36 seconds authors_default_kubevpn_a9a22
fc04e42799a5 nginx:latest "/docker-entrypoint.…" 37 seconds ago Up 37 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:8888->8888/tcp, 0.0.0.0:9080->9080/tcp nginx_default_kubevpn_a9a22
➜ ~
```
如果你只是想在本地启动镜像,可以用一种简单的方式:
```shell
kubevpn dev deployment/authors --no-proxy
```
例如:
```shell
➜ ~ kubevpn dev deployment/authors --no-proxy
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
tar: removing leading '/' from member names
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/5631078868924498209:/var/run/secrets/kubernetes.io/serviceaccount
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
/var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/1548572512863475037:/var/run/secrets/kubernetes.io/serviceaccount
create docker network 56c25058d4b7498d02c2c2386ccd1b2b127cb02e8a1918d6d24bffd18570200e
Created container: nginx_default_kubevpn_ff34b
Wait container nginx_default_kubevpn_ff34b to be running...
Container nginx_default_kubevpn_ff34b is running on port 80/tcp:80 8888/tcp:8888 9080/tcp:9080 now
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Created main container: authors_default_kubevpn_ff34b
2023/09/30 14:02:31 Start listening http port 9080 ...
```
此时程序会挂起,默认为显示日志
如果你想指定在本地启动容器的镜像, 可以使用参数 `--dev-image`, 当本地不存在该镜像时,
会从对应的镜像仓库拉取。如果你想指定启动参数,可以使用 `--entrypoint`
参数,替换为你想要执行的命令,比如 `--entrypoint /bin/bash`, 更多使用参数,请参见 `kubevpn dev --help`.
### DinD ( Docker in Docker ) 在 Docker 中使用 kubevpn
如果你想在本地使用 Docker in Docker (DinD) 的方式启动开发模式, 由于程序会读写 `/tmp`
目录,您需要手动添加参数 `-v /tmp:/tmp`, 还有一点需要注意, 如果使用 DinD
模式,为了共享容器网络和 pid, 还需要指定参数 `--network`
例如:
```shell
docker run -it --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v ~/.kube/config:/root/.kube/config --platform linux/amd64 ghcr.io/kubenetworks/kubevpn:latest
```
```shell
➜ ~ docker run -it --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v ~/.kube/vke:/root/.kube/config --platform linux/amd64 ghcr.io/kubenetworks/kubevpn:latest
Unable to find image 'ghcr.io/kubenetworks/kubevpn:latest' locally
latest: Pulling from ghcr.io/kubenetworks/kubevpn
9c704ecd0c69: Already exists
4987d0a976b5: Pull complete
8aa94c4fc048: Pull complete
526fee014382: Pull complete
6c1c2bedceb6: Pull complete
97ac845120c5: Pull complete
ca82aef6a9eb: Pull complete
1fd9534c7596: Pull complete
588bd802eb9c: Pull complete
Digest: sha256:368db2e0d98f6866dcefd60512960ce1310e85c24a398fea2a347905ced9507d
Status: Downloaded newer image for ghcr.io/kubenetworks/kubevpn:latest
WARNING: image with reference ghcr.io/kubenetworks/kubevpn was found but does not match the specified platform: wanted linux/amd64, actual: linux/arm64
root@5732124e6447:/app# kubevpn dev deployment/authors --headers user=naison --entrypoint sh
hostname is 5732124e6447
Starting connect
Got network CIDR from cache
Use exist traffic manager
Forwarding port...
Connected tunnel
Adding route...
Configured DNS service
Injecting inbound sidecar for deployment/authors
Patching workload deployment/authors
Checking rollout status for deployment/authors
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
deployment "authors" successfully rolled out
Rollout successfully for Deployment.apps/authors
tar: removing leading '/' from member names
/tmp/6460902982794789917:/var/run/secrets/kubernetes.io/serviceaccount
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets
/tmp/5028895788722532426:/var/run/secrets/kubernetes.io/serviceaccount
Network mode is container:d0b3dab8912a
Created container: nginx_default_kubevpn_6df63
Wait container nginx_default_kubevpn_6df63 to be running...
Container nginx_default_kubevpn_6df63 is running now
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Created main container: authors_default_kubevpn_6df5f
/opt/microservices # ps -ef
PID USER TIME COMMAND
1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash
14 root 0:02 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn kubevpn dev deployment/authors --headers
25 root 0:01 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon
37 root 0:04 {kubevpn} /usr/bin/qemu-x86_64 /usr/local/bin/kubevpn /usr/local/bin/kubevpn daemon --sudo
53 root 0:00 nginx: master process nginx -g daemon off;
(4/4) Installing curl (8.0.1-r0)
Executing busybox-1.33.1-r3.trigger
OK: 8 MiB in 19 packagesnx: worker process
/opt/microservices #
/opt/microservices # cat > hello.go <<EOF
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
_, _ = io.WriteString(writer, "Hello world!")
fmt.Println(">> Container Received request: %s %s from %s\n", request.Method, request.RequestURI, request.RemoteAddr)
})
fmt.Println("Start listening http port 9080 ...")
_ = http.ListenAndServe(":9080", nil)
}
EOF
/opt/microservices # go build hello.go
/opt/microservices #
//opt/microservices # ls -alh
total 12M
drwxr-xr-x 1 root root 26 Nov 4 10:29 .
drwxr-xr-x 1 root root 26 Oct 18 2021 ..
-rwxr-xr-x 1 root root 6.3M Oct 18 2021 app
-rwxr-xr-x 1 root root 5.8M Nov 4 10:29 hello
-rw-r--r-- 1 root root 387 Nov 4 10:28 hello.go
/opt/microservices #
/opt/microservices # apk add curl
OK: 8 MiB in 19 packages
/opt/microservices # ./hello &
/opt/microservices # Start listening http port 9080 ...
[2]+ Done ./hello
/opt/microservices # curl localhost:9080
>> Container Received request: GET / from 127.0.0.1:41230
Hello world!/opt/microservices #
/opt/microservices # curl authors:9080/health -H "foo: bar"
>>Received request: GET /health from 198.19.0.109:57930
Hello world!/opt/microservices #
/opt/microservices # curl localhost:9080/health
{"status":"Authors is healthy"}/opt/microservices # exit
Created container: default_authors
Wait container default_authors to be running...
Container default_authors is running now
Disconnecting from the cluster...
Leaving workload deployments.apps/authors
Disconnecting from the cluster...
Performing cleanup operations
Clearing DNS settings
root@d0b3dab8912a:/app# exit
exit
➜ ~
```
可以看到实际上是在本地使用 `Docker` 启动了三个容器。
```text
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1cd576b51b66 naison/authors:latest "sh" 4 minutes ago Up 4 minutes authors_default_kubevpn_6df5f
56a6793df82d nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes nginx_default_kubevpn_6df63
d0b3dab8912a ghcr.io/kubenetworks/kubevpn:v2.0.0 "/bin/bash" 5 minutes ago Up 5 minutes upbeat_noyce
➜ ~
```
### 支持多种协议
支持 OSI 模型三层及三层以上的协议,例如:
- TCP
- UDP
- HTTP
- ICMP
- gRPC
- Thrift
- WebSocket
- HTTP
- ...
### 支持三大平台
@@ -219,5 +642,21 @@ Hello world!%
- Linux
- Windows
Windows
下需要安装 [PowerShell](https://docs.microsoft.com/zh-cn/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.2)
## 架构
[架构](https://kubevpn.dev/docs/architecture/connect)
## 贡献代码
所有都是欢迎的,只是打开一个问题也是受欢迎的~
如果你想在本地电脑上调试项目,可以按照这样的步骤:
- 使用喜欢的 IDE Debug 启动 daemon 和 sudo daemon 两个后台进程。(本质上是两个 GRPC server
- 添加断点给文件 `pkg/daemon/action/connect.go:21`
- 新开个终端,执行命令 `make kubevpn`
- 然后运行命令 `./bin/kubevpn connect` 这样将会击中断点
### 支持者
[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://jb.gg/OpenSourceSupport)

24
TODO.MD
View File

@@ -1,24 +0,0 @@
## TODO
- [x] 访问集群网络
- [x] 域名解析功能
- [x] 支持多个 service 反向代理
- [x] 短域名解析
- [x] 优化 DHCP 功能
- [x] 支持多种类型,例如 statefulset, replicaset...
- [ ] 支持 ipv6
- [x] 自己实现 socks5 协议
- [ ] 考虑是否需要把 openvpn tap/tun 驱动作为后备方案
- [x] 加入 TLS 以提高安全性
- [ ] 写个 CNI 网络插件,直接提供 VPN 功能
- [ ] 优化重连逻辑
- [x] 支持 service mesh
- [ ] service mesh 支持多端口
- [x] 使用自己写的 proxy 替换 envoy
- [ ] 优化性能Windows 上考虑使用 IPC 通信
- [x] 自己写个 control plane
- [ ] 考虑是否将 control plane 和服务分开
- [ ] 写单元测试,优化 GitHub action
- [ ] Linux 和 macOS 也改用 WireGuard library
- [ ] 探测是否有重复路由的 utun设备禁用 `sudo ifconfig utun1 down`

34
build/Dockerfile Normal file
View File

@@ -0,0 +1,34 @@
FROM envoyproxy/envoy:v1.25.0 AS envoy
FROM golang:1.23 AS builder
ARG BASE=github.com/wencaiwulue/kubevpn
COPY . /go/src/$BASE
WORKDIR /go/src/$BASE
RUN make kubevpn
FROM debian:bookworm-slim
ARG BASE=github.com/wencaiwulue/kubevpn
RUN apt-get update && apt-get install -y openssl iptables curl dnsutils \
&& if [ $(uname -m) = "x86_64" ]; then \
echo "The architecture is AMD64"; \
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"; \
elif [ $(uname -m) = "aarch64" ]; then \
echo "The architecture is ARM64"; \
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"; \
else \
echo "Unsupported architecture."; \
exit 1; \
fi \
&& chmod +x kubectl && mv kubectl /usr/local/bin \
&& apt-get remove -y curl \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /go/src/$BASE/bin/kubevpn /usr/local/bin/kubevpn
COPY --from=envoy /usr/local/bin/envoy /usr/local/bin/envoy

6
build/dlv.Dockerfile Normal file
View File

@@ -0,0 +1,6 @@
FROM golang:1.23 as delve
RUN curl --location --output delve-1.23.1.tar.gz https://github.com/go-delve/delve/archive/v1.23.1.tar.gz \
&& tar xzf delve-1.23.1.tar.gz
RUN cd delve-1.23.1 && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /go/dlv -ldflags '-extldflags "-static"' ./cmd/dlv/
FROM busybox
COPY --from=delve /go/dlv /bin/dlv

37
build/local.Dockerfile Normal file
View File

@@ -0,0 +1,37 @@
FROM golang:1.23 AS builder
RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct
RUN go install github.com/go-delve/delve/cmd/dlv@latest
FROM envoyproxy/envoy:v1.25.0 AS envoy
FROM ubuntu:latest
RUN sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl \
net-tools iptables iputils-ping lsof iproute2 tcpdump binutils traceroute conntrack socat iperf3 \
apt-transport-https ca-certificates curl
RUN if [ $(uname -m) = "x86_64" ]; then \
echo "The architecture is AMD64"; \
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && chmod +x kubectl && mv kubectl /usr/local/bin; \
elif [ $(uname -m) = "aarch64" ]; then \
echo "The architecture is ARM64"; \
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl" && chmod +x kubectl && mv kubectl /usr/local/bin; \
else \
echo "Unsupported architecture."; \
fi
ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive
RUN apt update \
&& apt install -y tzdata \
&& ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone \
&& dpkg-reconfigure --frontend noninteractive tzdata \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY bin/kubevpn /usr/local/bin/kubevpn
COPY --from=envoy /usr/local/bin/envoy /usr/local/bin/envoy
COPY --from=builder /go/bin/dlv /usr/local/bin/dlv

34
build/test.Dockerfile Normal file
View File

@@ -0,0 +1,34 @@
FROM envoyproxy/envoy:v1.25.0 AS envoy
FROM golang:1.23 AS builder
ARG BASE=github.com/wencaiwulue/kubevpn
COPY . /go/src/$BASE
WORKDIR /go/src/$BASE
RUN make kubevpn
FROM debian:bookworm-slim
ARG BASE=github.com/wencaiwulue/kubevpn
RUN apt-get update && apt-get install -y openssl iptables curl dnsutils \
&& if [ $(uname -m) = "x86_64" ]; then \
echo "The architecture is AMD64"; \
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"; \
elif [ $(uname -m) = "aarch64" ]; then \
echo "The architecture is ARM64"; \
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"; \
else \
echo "Unsupported architecture."; \
exit 1; \
fi \
&& chmod +x kubectl && mv kubectl /usr/local/bin \
&& apt-get remove -y curl \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /go/src/$BASE/bin/kubevpn /usr/local/bin/kubevpn
COPY --from=envoy /usr/local/bin/envoy /usr/local/bin/envoy

590
charts/index.yaml Normal file
View File

@@ -0,0 +1,590 @@
apiVersion: v1
entries:
kubevpn:
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.13
created: "2025-06-01T11:26:39.769366159Z"
description: A Helm chart for KubeVPN
digest: 167b52f7f59b0a6c01c2660d1a0a9a71c315eeeabc0cf9ff1047ef5dfd4a06e6
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.13/kubevpn-2.7.13.tgz
version: 2.7.13
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.12
created: "2025-05-23T03:38:02.484001975Z"
description: A Helm chart for KubeVPN
digest: b9e28ceda8bb07b42ec37eb2d6b283496d83645479b2f1f4e921d9c462eeb54e
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.12/kubevpn-2.7.12.tgz
version: 2.7.12
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.11
created: "2025-05-18T09:03:21.60777933Z"
description: A Helm chart for KubeVPN
digest: ee30c2533dff51fa389767e56931583cdfff8c5fca7d6c9698f521c6fc508d42
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.11/kubevpn-2.7.11.tgz
version: 2.7.11
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.10
created: "2025-05-14T13:08:51.09371872Z"
description: A Helm chart for KubeVPN
digest: fd23dd5bf0c3a9343d73276c4997a34027a93c1a88667265d92297630579d165
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.10/kubevpn-2.7.10.tgz
version: 2.7.10
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.9
created: "2025-05-12T09:14:52.66116293Z"
description: A Helm chart for KubeVPN
digest: 56e022017177603290575849553c2e9c19f6a1691288dbd67c32a2fdcbde0834
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.9/kubevpn-2.7.9.tgz
version: 2.7.9
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.8
created: "2025-05-10T15:46:13.342045201Z"
description: A Helm chart for KubeVPN
digest: bfab5a7e4e1e795071a7ce3fd7713b517aa447d967ec58500e5a551564869109
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.8/kubevpn-2.7.8.tgz
version: 2.7.8
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.7
created: "2025-05-09T06:43:01.403047355Z"
description: A Helm chart for KubeVPN
digest: 14b3e7873aa71fa7a380631c83be8df1dfb8d0ccb49eb6746aa4f83e3df934f6
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.7/kubevpn-2.7.7.tgz
version: 2.7.7
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.6
created: "2025-05-07T11:46:09.644201893Z"
description: A Helm chart for KubeVPN
digest: 2146d5245440dff7d551ccc745aa1d9476d4f42053ff8a80f33f835d8da57712
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.6/kubevpn-2.7.6.tgz
version: 2.7.6
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.5
created: "2025-05-07T01:56:15.201307242Z"
description: A Helm chart for KubeVPN
digest: 34799e9605b3048aac75484bb32fb6c70f9e7eb7470e9b77c51be075a548c25e
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.5/kubevpn-2.7.5.tgz
version: 2.7.5
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.4
created: "2025-05-06T17:01:13.789138284Z"
description: A Helm chart for KubeVPN
digest: 5c6f2d1a178e917ac83ec72d0a46de9a0ff68f80a3aeb813d15dfb92c8ad36be
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.4/kubevpn-2.7.4.tgz
version: 2.7.4
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.3
created: "2025-05-06T15:40:24.505449375Z"
description: A Helm chart for KubeVPN
digest: 86ef4b1de6ea15f6738824f7c389a891f53500b9163b1288847172eb7dc6817e
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.3/kubevpn-2.7.3.tgz
version: 2.7.3
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.2
created: "2025-04-25T15:40:08.296727519Z"
description: A Helm chart for KubeVPN
digest: 8711dae30f4ff9bc9cea018fa16ae70087a17af42262f7f31c43950a34fffa08
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.2/kubevpn-2.7.2.tgz
version: 2.7.2
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.1
created: "2025-04-15T15:18:20.818055207Z"
description: A Helm chart for KubeVPN
digest: 79c40c942fd2cfcca63dd82921e04871680838f01717c6fcb3ee06bfb7f59535
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.1/kubevpn-2.7.1.tgz
version: 2.7.1
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.7.0
created: "2025-04-12T05:37:01.063235951Z"
description: A Helm chart for KubeVPN
digest: a4b4de15f474fba43367fc7239c31e2020a6a1e0e3b29e02eb653cb9922b02e8
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.7.0/kubevpn-2.7.0.tgz
version: 2.7.0
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.6.0
created: "2025-04-06T12:54:49.852649414Z"
description: A Helm chart for KubeVPN
digest: 58d930de19ac808e9f0ee501fe6f74b6f38376692708fc94fe7200496d9c5ca2
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.6.0/kubevpn-2.6.0.tgz
version: 2.6.0
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.5.1
created: "2025-04-03T15:46:28.062220333Z"
description: A Helm chart for KubeVPN
digest: 6daf003256c42bb0db414eb17eb06294e46d33bc6c63f01419012a37318d0d2f
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.5.1/kubevpn-2.5.1.tgz
version: 2.5.1
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.5.0
created: "2025-03-31T05:36:16.050204161Z"
description: A Helm chart for KubeVPN
digest: 301137b1599c232efd61ce9360e0a60da89e0a5c2eb076750bf461b38d26cfaf
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.5.0/kubevpn-2.5.0.tgz
version: 2.5.0
- annotations:
app: kubevpn
apiVersion: v2
appVersion: v2.4.3
created: "2025-03-30T13:48:42.333380676Z"
description: A Helm chart for KubeVPN
digest: 8ef28a43cb3d04f071445cf7d1199aba7392d78e1941707bab82853c5541c93c
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.4.3/kubevpn-2.4.3.tgz
version: 2.4.3
- apiVersion: v2
appVersion: v2.4.2
created: "2025-03-23T12:53:35.793492243Z"
description: A Helm chart for KubeVPN
digest: c627f69ac904ddb41c396909873425d85264fb3393d550fa1b0e8d2abfc402e9
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.4.2/kubevpn-2.4.2.tgz
version: 2.4.2
- apiVersion: v2
appVersion: v2.4.1
created: "2025-03-16T09:48:30.691242519Z"
description: A Helm chart for KubeVPN
digest: 1766431ce46b43758353928188cc993832e41cd0e352c9bc7991390bbbf41b04
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.4.1/kubevpn-2.4.1.tgz
version: 2.4.1
- apiVersion: v2
appVersion: v2.4.0
created: "2025-03-14T14:16:56.392516206Z"
description: A Helm chart for KubeVPN
digest: ffece68d3234ba629e02456fd3b0d31b5d2d1330c4c7f5d82ac2e0e1e97d82f3
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.4.0/kubevpn-2.4.0.tgz
version: 2.4.0
- apiVersion: v2
appVersion: v2.3.13
created: "2025-02-23T14:30:35.221348419Z"
description: A Helm chart for KubeVPN
digest: e79cdd07eae2ba3f36997debf898b091e1e68412fde7a34e823bad902e803105
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.13/kubevpn-2.3.13.tgz
version: 2.3.13
- apiVersion: v2
appVersion: v2.3.12
created: "2025-02-13T07:46:06.029130129Z"
description: A Helm chart for KubeVPN
digest: 0b7d9f8b4cd306377e4452a9d86530387afcae379e11665909b90e15f2d82a04
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.12/kubevpn-2.3.12.tgz
version: 2.3.12
- apiVersion: v2
appVersion: v2.3.11
created: "2025-02-03T09:24:54.033585049Z"
description: A Helm chart for KubeVPN
digest: a54a2ed19e6f4aa5c274186d6b188c0230244582055905155c4620ebe8864838
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.11/kubevpn-2.3.11.tgz
version: 2.3.11
- apiVersion: v2
appVersion: v2.3.10
created: "2025-01-24T13:36:34.489289734Z"
description: A Helm chart for KubeVPN
digest: 987b73399637eee01570492115114696fdb054074507f0d16e47d077e4ea770c
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.10/kubevpn-2.3.10.tgz
version: 2.3.10
- apiVersion: v2
appVersion: v2.3.9
created: "2024-12-21T15:29:42.173109915Z"
description: A Helm chart for KubeVPN
digest: 0f9dd91504c1d1c3149cca785f0a9d72ef860d002ee73590f41e3d8decc99365
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.9/kubevpn-2.3.9.tgz
version: 2.3.9
- apiVersion: v2
appVersion: v2.3.8
created: "2024-12-19T14:19:38.126241384Z"
description: A Helm chart for KubeVPN
digest: 84239f1bce053eaa9314e53b820ad0ba32bbc51c37dcac6ae8abd03bef6f7fd2
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.8/kubevpn-2.3.8.tgz
version: 2.3.8
- apiVersion: v2
appVersion: v2.3.7
created: "2024-12-14T17:25:08.398840622Z"
description: A Helm chart for KubeVPN
digest: 437faa6cd98e81c4ad2c1b48c9ef7a33e7d435cf6343c5cc2c88ea251b2a545b
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.7/kubevpn-2.3.7.tgz
version: 2.3.7
- apiVersion: v2
appVersion: v2.3.6
created: "2024-12-09T11:52:04.779835011Z"
description: A Helm chart for KubeVPN
digest: 7b23d14f6aea4410d68911d202199f15c88cb96cef8edbd94d4a95e9b9254bf7
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.6/kubevpn-2.3.6.tgz
version: 2.3.6
- apiVersion: v2
appVersion: v2.3.5
created: "2024-12-06T14:40:11.685095653Z"
description: A Helm chart for KubeVPN
digest: c2a85f446af834b60308b1384e6cae5662229c34370053319c0f759f650a1cb5
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.5/kubevpn-2.3.5.tgz
version: 2.3.5
- apiVersion: v2
appVersion: v2.3.4
created: "2024-11-29T13:03:24.255324387Z"
description: A Helm chart for KubeVPN
digest: 2804aa624f6139695f3fb723bdc6ba087492bcd8810baf7196a1ae88bd2a62b5
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.4/kubevpn-2.3.4.tgz
version: 2.3.4
- apiVersion: v2
appVersion: v2.3.3
created: "2024-11-22T14:54:13.795282085Z"
description: A Helm chart for KubeVPN
digest: 33cbbc9312e7b7e415fb14f80f17df50d305194617bcf75d1501227cb90b8f32
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.3/kubevpn-2.3.3.tgz
version: 2.3.3
- apiVersion: v2
appVersion: v2.3.2
created: "2024-11-18T11:52:12.076510627Z"
description: A Helm chart for KubeVPN
digest: cdb38ab84bf1649ac4280f6996060c49a095f9c056044cd5f691e7bf4f259dad
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.2/kubevpn-2.3.2.tgz
version: 2.3.2
- apiVersion: v2
appVersion: v2.3.1
created: "2024-11-15T13:36:37.056311943Z"
description: A Helm chart for KubeVPN
digest: 10c1200241309be4ec2eb88e9689ebbf96704c8fad270e6fda30047135aeccf2
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.3.1/kubevpn-2.3.1.tgz
version: 2.3.1
- apiVersion: v2
appVersion: v2.2.22
created: "2024-10-30T08:46:08.845218523Z"
description: A Helm chart for KubeVPN
digest: c2dc336383d7de2fb97cfd40a15e9f6c29a9a598484b88515a98bcaeb4925eda
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.22/kubevpn-2.2.22.tgz
version: 2.2.22
- apiVersion: v2
appVersion: v2.2.21
created: "2024-10-25T14:10:25.545716679Z"
description: A Helm chart for KubeVPN
digest: 98ae51247535525ff6a10b5f493d8bfc573af62759432f7aa54dd7eb6edeffd5
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.21/kubevpn-2.2.21.tgz
version: 2.2.21
- apiVersion: v2
appVersion: v2.2.20
created: "2024-10-20T04:00:07.263734809Z"
description: A Helm chart for KubeVPN
digest: 7863701dff5b3fce0795ee8e0b73044b7c88f8777c86a65adc1f5563123565dc
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.20/kubevpn-2.2.20.tgz
version: 2.2.20
- apiVersion: v2
appVersion: v2.2.19
created: "2024-10-10T00:47:08.858011096Z"
description: A Helm chart for KubeVPN
digest: be2c672081307c03b7fe6b635d524c8f3f73d70ae3316efa85e781a62c25a46d
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.19/kubevpn-2.2.19.tgz
version: 2.2.19
- apiVersion: v2
appVersion: v2.2.18
created: "2024-09-10T09:39:11.71407425Z"
description: A Helm chart for KubeVPN
digest: 2d953103425ca2a087a2d521c9297662f97b72e78cf831e947942f292bbcc643
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.18/kubevpn-2.2.18.tgz
version: 2.2.18
- apiVersion: v2
appVersion: v2.2.17
created: "2024-08-03T07:45:55.228743946Z"
description: A Helm chart for KubeVPN
digest: 476317ad82b2c59a623e1fca968c09a28554ebcabec337c1c363e7296bb27514
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.17/kubevpn-2.2.17.tgz
version: 2.2.17
- apiVersion: v2
appVersion: v2.2.16
created: "2024-07-26T13:43:50.473565863Z"
description: A Helm chart for KubeVPN
digest: 6cdb809d04687197a8defbf4349871c505ac699924833fecc210d8a6d82a9f20
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.16/kubevpn-2.2.16.tgz
version: 2.2.16
- apiVersion: v2
appVersion: v2.2.15
created: "2024-07-19T15:03:13.558586823Z"
description: A Helm chart for KubeVPN
digest: 279b24976cef25e1dd8a4cd612a7c6a5767cecd4ba386ccab80fc00db76117e7
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.15/kubevpn-2.2.15.tgz
version: 2.2.15
- apiVersion: v2
appVersion: v2.2.14
created: "2024-07-12T15:24:27.825047662Z"
description: A Helm chart for KubeVPN
digest: 52ab9b89ea3773792bf3839e4a7c23a9ea60a6c72547024dc0907c973a8d34b3
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.14/kubevpn-2.2.14.tgz
version: 2.2.14
- apiVersion: v2
appVersion: v2.2.13
created: "2024-07-05T15:08:40.140645659Z"
description: A Helm chart for KubeVPN
digest: 610c5528952826839d5636b8bd940ac907ab0e70377e37538063cb53a5f75443
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.13/kubevpn-2.2.13.tgz
version: 2.2.13
- apiVersion: v2
appVersion: v2.2.12
created: "2024-06-29T15:36:12.429229459Z"
description: A Helm chart for KubeVPN
digest: a129ac0efda2e2967937407b904d59122e7b9725fb225c0bcbfdf2260337c032
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.12/kubevpn-2.2.12.tgz
version: 2.2.12
- apiVersion: v2
appVersion: v2.2.11
created: "2024-06-21T14:13:53.982206886Z"
description: A Helm chart for KubeVPN
digest: 3a7fa4cb3e1785da68e422ef151a3c7f621fbe76862b557ae2750af70d34e1ad
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.11/kubevpn-2.2.11.tgz
version: 2.2.11
- apiVersion: v2
appVersion: v2.2.10
created: "2024-05-21T06:46:20.368800554Z"
description: A Helm chart for KubeVPN
digest: 89be252c9eedb13560224550f06270f8be88049edfb0a46ca170ab5c8c493a6c
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.10/kubevpn-2.2.10.tgz
version: 2.2.10
- apiVersion: v2
appVersion: v2.2.9
created: "2024-05-14T11:50:54.700148975Z"
description: A Helm chart for KubeVPN
digest: e94debe7c904e21f791c1e3bb877ca8132888a3bb3c53beaa74e2ff1e7dd8769
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.9/kubevpn-2.2.9.tgz
version: 2.2.9
- apiVersion: v2
appVersion: v2.2.8
created: "2024-05-03T15:50:13.647253665Z"
description: A Helm chart for KubeVPN
digest: 9e18d0d02f123e5d8f096362daa5e6893d5db1e8447a632585ae23d6ce755489
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.8/kubevpn-2.2.8.tgz
version: 2.2.8
- apiVersion: v2
appVersion: v2.2.7
created: "2024-04-27T12:11:35.594701859Z"
description: A Helm chart for KubeVPN
digest: 3828f5b20d6bf4c0c7d94654cc33fd8d7b4c5f2aa20a3cc18d18b9298f459456
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.7/kubevpn-2.2.7.tgz
version: 2.2.7
- apiVersion: v2
appVersion: v2.2.6
created: "2024-04-16T05:44:31.777079658Z"
description: A Helm chart for KubeVPN
digest: 63668930b99e6c18f6dd77a25e5ce2d21579d52a83451f58be3bc0ca32678829
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.6/kubevpn-2.2.6.tgz
version: 2.2.6
- apiVersion: v2
appVersion: v2.2.5
created: "2024-04-14T08:46:13.877936123Z"
description: A Helm chart for KubeVPN
digest: 8509aeec7584935344bdf465efd8f0d5efb58ef1b7a31fd2738e5c2790f680c4
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.5/kubevpn-2.2.5.tgz
version: 2.2.5
- apiVersion: v2
appVersion: v2.2.4
created: "2024-04-02T05:15:00.372823536Z"
description: A Helm chart for KubeVPN
digest: 07e87e648b7ad5688146a356c93c1771e94485c2fd9d5441553d94ce6371c19f
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.4/kubevpn-2.2.4.tgz
version: 2.2.4
- apiVersion: v2
appVersion: v2.2.3
created: "2024-03-03T11:52:37.856463964Z"
description: A Helm chart for KubeVPN
digest: cb1b8c210259292488548853bdeb2eb9ef4c60d1643e0d6537174349514dc8e9
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.3/kubevpn-2.2.3.tgz
version: 2.2.3
- apiVersion: v2
appVersion: v2.2.2
created: "2024-02-15T13:35:35.121411893Z"
description: A Helm chart for KubeVPN
digest: b7589312eab83e50db9ae5703a30e76f0b40fd280c81d102a823aeeb61e14c1c
name: kubevpn
type: application
urls:
- https://github.com/kubenetworks/kubevpn/releases/download/v2.2.2/kubevpn-2.2.2.tgz
version: 2.2.2
generated: "2025-06-01T11:26:39.769535105Z"

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -0,0 +1,8 @@
apiVersion: v2
name: kubevpn
description: A Helm chart for KubeVPN
type: application
version: 0.1.0
appVersion: "1.16.0"
annotations:
app: kubevpn

24
charts/kubevpn/README.md Normal file
View File

@@ -0,0 +1,24 @@
# Helm charts for KubeVPN server
Use helm to install kubevpn server means use cluster mode. All user will use this instance.
- Please make sure users should have permission to namespace `kubevpn`.
- Otherwise, will fall back to create `kubevpn` deployment in own namespace.
## Install with default mode
```shell
helm install kubevpn kubevpn/kubevpn -n kubevpn --create-namespace
```
in China, you can use tencent image registry
```shell
helm install kubevpn kubevpn/kubevpn --set image.repository=ccr.ccs.tencentyun.com/kubevpn/kubevpn -n kubevpn --create-namespace
```
## AWS Fargate cluster
```shell
helm install kubevpn kubevpn/kubevpn --set netstack=gvisor -n kubevpn --create-namespace
```

View File

@@ -0,0 +1,4 @@
1. Connect to cluster network by running these commands:
kubevpn connect --namespace {{ include "kubevpn.namespace" . }}
export POD_IP=$(kubectl get pods --namespace {{ include "kubevpn.namespace" . }} -l "app.kubernetes.io/name={{ include "kubevpn.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].status.podIP}")
ping $POD_IP

View File

@@ -0,0 +1,82 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "kubevpn.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "kubevpn.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "kubevpn.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "kubevpn.labels" -}}
helm.sh/chart: {{ include "kubevpn.chart" . }}
app: kubevpn-traffic-manager
{{ include "kubevpn.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "kubevpn.selectorLabels" -}}
app.kubernetes.io/name: {{ include "kubevpn.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "kubevpn.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "kubevpn.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Namespace
1. special by -n
2. use default namespace kubevpn
*/}}
{{- define "kubevpn.namespace" -}}
{{- if .Release.Namespace }}
{{- if eq .Release.Namespace "default" }}
{{- .Values.namespace }}
{{- else }}
{{- .Release.Namespace }}
{{- end }}
{{- else if .Values.namespace }}
{{- .Values.namespace }}
{{- else }}
{{- .Values.namespace }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
data:
DHCP: ""
DHCP6: ""
ENVOY_CONFIG: ""
IPv4_POOLS: "{{ .Values.cidr.pod }} {{ .Values.cidr.service }}"
REF_COUNT: "0"

View File

@@ -0,0 +1,138 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
labels:
{{- include "kubevpn.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "kubevpn.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "kubevpn.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "kubevpn.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- args:
{{- if eq .Values.netstack "system" }}
- |
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
update-alternatives --set iptables /usr/sbin/iptables-legacy
iptables -P INPUT ACCEPT
ip6tables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
ip6tables -P FORWARD ACCEPT
iptables -t nat -A POSTROUTING -s ${CIDR4} -o eth0 -j MASQUERADE
ip6tables -t nat -A POSTROUTING -s ${CIDR6} -o eth0 -j MASQUERADE
kubevpn server -l "tcp://:10800" -l "tun://:8422?net=${TunIPv4}&net6=${TunIPv6}" -l "gtcp://:10801" -l "gudp://:10802"
{{- else }}
- kubevpn server -l "tcp://:10800" -l "gtcp://:10801" -l "gudp://:10802"
{{- end }}
command:
- /bin/sh
- -c
env:
- name: CIDR4
value: 198.19.0.0/16
- name: CIDR6
value: 2001:2::/64
- name: TunIPv4
value: 198.19.0.100/16
- name: TunIPv6
value: 2001:2::9999/64
envFrom:
- secretRef:
name: {{ include "kubevpn.fullname" . }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: vpn
ports:
- containerPort: {{ .Values.service.port8422 }}
name: 8422-for-udp
protocol: UDP
- containerPort: {{ .Values.service.port10800 }}
name: 10800-for-tcp
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- if eq .Values.netstack "system" }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- end }}
- args:
- control-plane
- --watchDirectoryFilename
- /etc/envoy/envoy-config.yaml
command:
- kubevpn
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: control-plane
ports:
- containerPort: {{ .Values.service.port9002 }}
name: 9002-for-envoy
protocol: TCP
resources:
{{- toYaml .Values.resourcesSmall | nindent 12 }}
volumeMounts:
- mountPath: /etc/envoy
name: envoy-config
readOnly: true
- args:
- webhook
command:
- kubevpn
envFrom:
- secretRef:
name: {{ include "kubevpn.fullname" . }}
env:
- name: "POD_NAMESPACE"
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: webhook
ports:
- containerPort: 80
name: 80-for-webhook
protocol: TCP
resources:
{{- toYaml .Values.resourcesSmall | nindent 12 }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,33 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
labels:
{{- include "kubevpn.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "kubevpn.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,73 @@
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
labels:
{{- include "kubevpn.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "kubevpn.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
restartPolicy: Never
serviceAccountName: {{ include "kubevpn.serviceAccountName" . }}
containers:
- name: label-ns
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- /bin/bash
- -c
args:
- |2-
echo "Label namespace {{ include "kubevpn.namespace" . }}"
kubectl label ns {{ include "kubevpn.namespace" . }} ns={{ include "kubevpn.namespace" . }}
echo "Generating https certificate"
openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -subj "/CN={{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}" -addext "subjectAltName=DNS:{{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}.svc.cluster.local,DNS:{{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}.svc,DNS:{{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }},DNS:localhost,IP:127.0.0.1" -keyout server.key -out server.crt
export TLS_CRT=$(cat server.crt | base64 | tr -d '\n')
echo "Patch mutatingwebhookconfigurations {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}"
kubectl patch mutatingwebhookconfigurations {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }} -p "{\"webhooks\":[{\"name\":\"{{ include "kubevpn.fullname" . }}.naison.io\",\"sideEffects\":\"None\",\"admissionReviewVersions\":[\"v1\", \"v1beta1\"],\"clientConfig\":{\"service\":{\"namespace\":\"{{ include "kubevpn.namespace" . }}\",\"name\":\"{{ include "kubevpn.fullname" . }}\"},\"caBundle\":\"$TLS_CRT\"}}]}"
export TLS_KEY=$(cat server.key | base64 | tr -d '\n')
echo "Patch secret {{ include "kubevpn.fullname" . }}"
kubectl patch secret {{ include "kubevpn.fullname" . }} -n {{ include "kubevpn.namespace" . }} -p "{\"data\":{\"tls_key\":\"$TLS_KEY\",\"tls_crt\":\"$TLS_CRT\"}}"
echo "Restart the pods..."
kubectl scale -n {{ include "kubevpn.namespace" . }} --replicas=0 deployment/{{ include "kubevpn.fullname" . }}
kubectl scale -n {{ include "kubevpn.namespace" . }} --replicas=1 deployment/{{ include "kubevpn.fullname" . }}
export POOLS=$(kubectl get cm {{ include "kubevpn.fullname" . }} -n {{ include "kubevpn.namespace" . }} -o jsonpath='{.data.IPv4_POOLS}')
if [[ -z "${POOLS// }" ]];then
echo "Cidr is empty"
echo "Get pod cidr..."
export POD_CIDR=$(kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' | tr -s '\n' ' ')
echo "Get service cidr..."
export SVC_CIDR=$(echo '{"apiVersion":"v1","kind":"Service","metadata":{"name":"kubevpn-get-svc-cidr-{{ include "kubevpn.namespace" . }}", "namespace": "{{ include "kubevpn.namespace" . }}"},"spec":{"clusterIP":"1.1.1.1","ports":[{"port":443}]}}' | kubectl apply -f - 2>&1 | sed 's/.*valid IPs is //')
echo "Pod cidr: $POD_CIDR, service cidr: $SVC_CIDR"
echo "Patch configmap {{ include "kubevpn.fullname" . }}"
kubectl patch configmap {{ include "kubevpn.fullname" . }} -n {{ include "kubevpn.namespace" . }} -p "{\"data\":{\"IPv4_POOLS\":\"$POD_CIDR $SVC_CIDR\"}}"
else
echo "Cidr is NOT empty"
fi
echo "Done~"
exit 0

View File

@@ -0,0 +1,35 @@
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}
namespace: {{ include "kubevpn.namespace" . }}
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
caBundle: {{ .Values.tls.crt }}
service:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
path: /pods
port: 80
failurePolicy: Ignore
matchPolicy: Equivalent
name: {{ include "kubevpn.fullname" . }}.naison.io
namespaceSelector: { }
objectSelector: { }
reinvocationPolicy: Never
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- DELETE
resources:
- pods
scope: Namespaced
sideEffects: None
timeoutSeconds: 15

View File

@@ -0,0 +1,70 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
rules:
- apiGroups:
- ""
resourceNames:
- {{ include "kubevpn.fullname" . }}
resources:
- configmaps
- secrets
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups: [ "" ]
resources: [ "namespaces" ]
resourceNames: ["{{ include "kubevpn.namespace" . }}"]
verbs:
- get
- patch
- apiGroups: [ "apps" ]
resources: [ "deployments/scale", "deployments" ]
resourceNames:
- {{ include "kubevpn.fullname" . }}
verbs:
- get
- update
- patch
- list
- apiGroups:
- ""
resources:
- services
verbs:
- create
- get
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
resourceNames:
- {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}
verbs:
- get
- list
- patch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch

View File

@@ -0,0 +1,27 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "kubevpn.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}
subjects:
- kind: ServiceAccount
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
roleRef:
kind: ClusterRole
name: {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}
apiGroup: rbac.authorization.k8s.io

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
type: Opaque
stringData:
tls_crt: {{ .Values.tls.crt }}
tls_key: {{ .Values.tls.key }}
tls_server_name: {{ include "kubevpn.fullname" . }}.{{ include "kubevpn.namespace" . }}

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "kubevpn.fullname" . }}
namespace: {{ include "kubevpn.namespace" . }}
labels:
{{- include "kubevpn.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- name: 8422-for-udp
port: {{ .Values.service.port8422 }}
protocol: UDP
targetPort: 8422
- name: 10800-for-tcp
port: {{ .Values.service.port10800 }}
protocol: TCP
targetPort: 10800
- name: 9002-for-envoy
port: {{ .Values.service.port9002 }}
protocol: TCP
targetPort: 9002
- name: 80-for-webhook
port: {{ .Values.service.port80 }}
protocol: TCP
targetPort: 80
- name: 53-for-dns
port: {{ .Values.service.port53 }}
protocol: UDP
targetPort: 53
selector:
{{- include "kubevpn.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,14 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "kubevpn.serviceAccountName" . }}
namespace: {{ include "kubevpn.namespace" . }}
labels:
{{- include "kubevpn.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
{{- end }}

120
charts/kubevpn/values.yaml Normal file
View File

@@ -0,0 +1,120 @@
# Default values for kubevpn.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# default namespace
namespace: kubevpn
# default is system mode, available ["system", "gvisor"]
# system: needs privilege permission and cap NET_ADMIN (Best experience)
# gvisor: no needs any additional permission (Best compatibility)
netstack: system
replicaCount: 1
image:
repository: ghcr.io/kubenetworks/kubevpn
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: [ ]
nameOverride: ""
fullnameOverride: "kubevpn-traffic-manager"
# this filed is import if configured this value
# if not configured, it will get this value from cluster automatically
cidr:
pod: ""
service: ""
tls:
# will auto generate in job
crt: ''''''
key: ''''''
serviceAccount:
# Specifies whether a service account should be created
create: true
# Automatically mount a ServiceAccount's API credentials?
automount: 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: ""
podAnnotations: { }
podLabels:
podSecurityContext: { }
# fsGroup: 2000
securityContext:
capabilities:
add:
- NET_ADMIN
privileged: true
runAsUser: 0
runAsGroup: 0
service:
type: ClusterIP
port8422: 8422
port9002: 9002
port10800: 10800
port80: 80
port53: 53
resources:
limits:
cpu: "2"
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi
resourcesSmall:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 1
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
# Additional volumes on the output Deployment definition.
volumes:
- configMap:
defaultMode: 420
items:
- key: ENVOY_CONFIG
path: envoy-config.yaml
name: kubevpn-traffic-manager
optional: false
name: envoy-config
# Additional volumeMounts on the output Deployment definition.
volumeMounts: [ ]
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: { }
tolerations: [ ]
affinity: { }

210
cmd/kubevpn/cmds/alias.go Normal file
View File

@@ -0,0 +1,210 @@
package cmds
import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/util/sets"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
yaml "sigs.k8s.io/yaml/goyaml.v3"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
// CmdAlias
/**
Name: test
Description: this is a test environment
Needs: test1
Flags:
- connect
- --kubeconfig=~/.kube/config
- --namespace=test
- --lite
---
Name: test1
Description: this is another test environment
Flags:
- connect
- --kubeconfig=~/.kube/jumper_config
- --namespace=test
- --extra-hosts=xxx.com
*/
func CmdAlias(f cmdutil.Factory) *cobra.Command {
var localFile, remoteAddr string
cmd := &cobra.Command{
Use: "alias",
Short: i18n.T("Config file alias to execute command simply"),
Long: templates.LongDesc(i18n.T(`
Config file alias to execute command simply, just like ssh alias config
Please point to an existing, complete config file:
1. Via the command-line flag --kubevpnconfig
2. Via the KUBEVPNCONFIG environment variable
3. In your home directory as ~/.kubevpn/config.yaml
It will read ~/.kubevpn/config.yaml file as config, also support special file path
by flag -f. It also supports depends relationship, like one cluster api server needs to
access via another cluster, you can use syntax needs. it will do action to needs cluster first
and then do action to target cluster
`)),
Example: templates.Examples(i18n.T(`
If you have following config in your ~/.kubevpn/config.yaml
Name: dev
Needs: jumper
Flags:
- connect
- --kubeconfig=~/.kube/config
- --namespace=default
- --lite
---
Name: jumper
Flags:
- connect
- --kubeconfig=~/.kube/jumper_config
- --namespace=test
- --extra-hosts=xxx.com
Config file support three field: Name,Needs,Flags
# Use kubevpn alias config to simply execute command, connect to cluster network by order: jumper --> dev
kubevpn alias dev
# kubevpn alias jumper, just connect to cluster jumper
kubevpn alias jumper
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
if localFile != "" {
_, err = os.Stat(localFile)
}
return err
},
Args: cobra.MatchAll(cobra.ExactArgs(1)),
RunE: func(cmd *cobra.Command, args []string) error {
configs, err := ParseAndGet(localFile, remoteAddr, args[0])
if err != nil {
return err
}
name, err := os.Executable()
if err != nil {
return err
}
for _, conf := range configs {
c := exec.Command(name, conf.Flags...)
c.Stdout = os.Stdout
c.Stdin = os.Stdin
c.Stderr = os.Stderr
fmt.Println(fmt.Sprintf("Name: %s", conf.Name))
if conf.Description != "" {
fmt.Println(fmt.Sprintf("Description: %s", conf.Description))
}
fmt.Println(fmt.Sprintf("Command: %v", c.Args))
err = c.Run()
if err != nil {
return err
}
}
return nil
},
}
cmd.Flags().StringVarP(&localFile, "kubevpnconfig", "f", util.If(os.Getenv("KUBEVPNCONFIG") != "", os.Getenv("KUBEVPNCONFIG"), config.GetConfigFile()), "Path to the kubevpnconfig file to use for CLI requests.")
cmd.Flags().StringVarP(&remoteAddr, "remote", "r", "", "Remote config file, eg: https://raw.githubusercontent.com/kubenetworks/kubevpn/master/pkg/config/config.yaml")
return cmd
}
func ParseAndGet(localFile, remoteAddr string, aliasName string) ([]Config, error) {
var content []byte
var err error
var path string
if localFile != "" {
path = localFile
content, err = os.ReadFile(path)
} else if remoteAddr != "" {
path = remoteAddr
content, err = util.DownloadFileStream(path)
} else {
path = config.GetConfigFile()
content, err = os.ReadFile(path)
}
if err != nil {
return nil, err
}
list, err := ParseConfig(content)
if err != nil {
return nil, err
}
configs, err := GetConfigs(list, aliasName)
if err != nil {
return nil, err
}
if len(configs) == 0 {
var names []string
for _, c := range list {
if c.Name != "" {
names = append(names, c.Name)
}
}
err = errors.New(fmt.Sprintf("Can't find any alias for the name: '%s', avaliable: \n[\"%s\"]\nPlease check config file: %s", aliasName, strings.Join(names, "\", \""), path))
return nil, err
}
return configs, nil
}
func ParseConfig(file []byte) ([]Config, error) {
decoder := yaml.NewDecoder(strings.NewReader(string(file)))
var configs []Config
for {
var cfg Config
err := decoder.Decode(&cfg)
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
configs = append(configs, cfg)
}
return configs, nil
}
func GetConfigs(configs []Config, name string) ([]Config, error) {
m := make(map[string]Config)
for _, config := range configs {
m[config.Name] = config
}
var result []Config
var set []string
for !sets.New[string](set...).Has(name) {
config, ok := m[name]
if ok {
result = append([]Config{config}, result...)
set = append(set, name)
name = config.Needs
if name == "" {
return result, nil
}
} else {
return result, nil
}
}
return nil, fmt.Errorf("loop jump detected: %s. verify your configuration", strings.Join(append(set, name), " -> "))
}
type Config struct {
Name string `yaml:"Name"`
Description string `yaml:"Description"`
Needs string `yaml:"Needs,omitempty"`
Flags []string `yaml:"Flags,omitempty"`
}

View File

@@ -0,0 +1,229 @@
package cmds
import (
"context"
"reflect"
"testing"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
)
func TestAlias(t *testing.T) {
str := `Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com`
_, err := ParseConfig([]byte(str))
if err != nil {
plog.G(context.Background()).Fatal(err)
}
}
func TestCheckLoop(t *testing.T) {
str := `Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com`
_, err := ParseConfig([]byte(str))
if err != nil {
plog.G(context.Background()).Fatal(err)
}
}
func TestLoop(t *testing.T) {
data := []struct {
Config string
Run string
ExpectError bool
ExpectOrder []string
}{
{
Config: `
Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Needs: test
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
`,
Run: "test",
ExpectError: true,
ExpectOrder: nil,
},
{
Config: `
Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
`,
Run: "test",
ExpectError: false,
ExpectOrder: []string{"test1", "test"},
},
{
Config: `
Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Needs: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
`,
Run: "test",
ExpectError: false,
ExpectOrder: []string{"test1", "test"},
},
{
Config: `
Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Needs: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
---
Name: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
`,
Run: "test",
ExpectError: false,
ExpectOrder: []string{"test2", "test1", "test"},
},
{
Config: `
Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Needs: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
---
Name: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
`,
Run: "test2",
ExpectError: false,
ExpectOrder: []string{"test2"},
},
{
Config: `
Name: test
Needs: test1
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
---
Name: test1
Needs: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
---
Name: test2
Flags:
- --kubeconfig=~/.kube/config
- --namespace=test
- --extra-hosts=xxx.com
`,
Run: "test1",
ExpectError: false,
ExpectOrder: []string{"test2", "test1"},
},
}
for _, datum := range data {
configs, err := ParseConfig([]byte(datum.Config))
if err != nil {
plog.G(context.Background()).Fatal(err)
}
getConfigs, err := GetConfigs(configs, datum.Run)
if err != nil && !datum.ExpectError {
plog.G(context.Background()).Fatal(err)
} else if err != nil {
}
if datum.ExpectError {
continue
}
var c []string
for _, config := range getConfigs {
c = append(c, config.Name)
}
if !reflect.DeepEqual(c, datum.ExpectOrder) {
plog.G(context.Background()).Fatalf("Not match, expect: %v, real: %v", datum.ExpectOrder, c)
}
}
}

188
cmd/kubevpn/cmds/clone.go Normal file
View File

@@ -0,0 +1,188 @@
package cmds
import (
"context"
"fmt"
"os"
pkgerr "github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
utilcomp "k8s.io/kubectl/pkg/util/completion"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
"github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl"
)
// CmdClone multiple cluster operate, can start up one deployment to another cluster
// kubectl exec POD_NAME -c CONTAINER_NAME /sbin/killall5 or ephemeralcontainers
func CmdClone(f cmdutil.Factory) *cobra.Command {
var options = handler.CloneOptions{}
var sshConf = &pkgssh.SshConfig{}
var extraRoute = &handler.ExtraRouteInfo{}
var transferImage bool
var syncDir string
var imagePullSecretName string
cmd := &cobra.Command{
Use: "clone",
Short: i18n.T("Clone workloads to run in same namespace with same volume、env、and network"),
Long: templates.LongDesc(i18n.T(`
Clone workloads to run in same namespace with same volume、env、and network
In this way, you can startup another deployment in same cluster or not, but with different image version,
it also supports service mesh proxy. only traffic with special header will hit to cloned_resource.
`)),
Example: templates.Examples(i18n.T(`
# clone
- clone deployment run into current cluster and current namespace
kubevpn clone deployment/productpage
- clone deployment run into current cluster with different namespace
kubevpn clone deployment/productpage -n test
- clone deployment run into another cluster
kubevpn clone deployment/productpage --target-kubeconfig ~/.kube/other-kubeconfig
- clone multiple workloads run into current cluster and current namespace
kubevpn clone deployment/authors deployment/productpage
or
kubevpn clone deployment authors productpage
# clone with mesh, traffic with header foo=bar, will hit cloned workloads, otherwise hit origin workloads
kubevpn clone deployment/productpage --headers foo=bar
# clone workloads which api-server behind of bastion host or ssh jump host
kubevpn clone deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem --headers foo=bar
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn clone service/productpage --ssh-alias <alias> --headers foo=bar
# Support ssh auth GSSAPI
kubevpn clone service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn clone service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn clone service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
plog.InitLoggerForClient()
// startup daemon process and sudo process
err = daemon.StartupDaemon(cmd.Context())
if err != nil {
return err
}
if transferImage {
err = regctl.TransferImageWithRegctl(cmd.Context(), config.OriginImage, config.Image)
}
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
_, _ = fmt.Fprintf(os.Stdout, "You must specify the type of resource to proxy. %s\n\n", cmdutil.SuggestAPIResources("kubevpn"))
fullCmdName := cmd.Parent().CommandPath()
usageString := "Required resource not specified."
if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") {
usageString = fmt.Sprintf("%s\nUse \"%s explain <resource>\" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName)
}
return cmdutil.UsageErrorf(cmd, usageString)
}
if syncDir != "" {
local, remote, err := util.ParseDirMapping(syncDir)
if err != nil {
return pkgerr.Wrapf(err, "options 'sync' is invalid, %s", syncDir)
}
options.LocalDir = local
options.RemoteDir = remote
} else {
options.RemoteDir = config.DefaultRemoteDir
}
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
if !sshConf.IsEmpty() {
if ip := util.GetAPIServerFromKubeConfigBytes(bytes); ip != nil {
extraRoute.ExtraCIDR = append(extraRoute.ExtraCIDR, ip.String())
}
}
req := &rpc.CloneRequest{
KubeconfigBytes: string(bytes),
Namespace: ns,
Headers: options.Headers,
Workloads: args,
ExtraRoute: extraRoute.ToRPC(),
OriginKubeconfigPath: util.GetKubeConfigPath(f),
Engine: string(options.Engine),
SshJump: sshConf.ToRPC(),
TargetContainer: options.TargetContainer,
TargetImage: options.TargetImage,
TransferImage: transferImage,
Image: config.Image,
ImagePullSecretName: imagePullSecretName,
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
LocalDir: options.LocalDir,
RemoteDir: options.RemoteDir,
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
resp, err := cli.Clone(cmd.Context(), req)
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.CloneResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
err = remove(cli, args)
return err
}
return err
}
util.Print(os.Stdout, config.Slogan)
return nil
},
}
cmd.Flags().StringToStringVarP(&options.Headers, "headers", "H", map[string]string{}, "Traffic with special headers (use `and` to match all headers) with reverse it to target cluster cloned workloads, If not special, redirect all traffic to target cluster cloned workloads. eg: --headers foo=bar --headers env=dev")
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &options.Engine)
cmdutil.AddContainerVarFlags(cmd, &options.TargetContainer, options.TargetContainer)
cmd.Flags().StringVar(&options.TargetImage, "target-image", "", "Clone container use this image to startup container, if not special, use origin image")
cmd.Flags().StringVar(&syncDir, "sync", "", "Sync local dir to remote pod dir. format: LOCAL_DIR:REMOTE_DIR, eg: ~/code:/app/code")
handler.AddExtraRoute(cmd.Flags(), extraRoute)
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
cmd.ValidArgsFunction = utilcomp.ResourceTypeAndNameCompletionFunc(f)
return cmd
}
func remove(cli rpc.DaemonClient, args []string) error {
resp, err := cli.Remove(context.Background(), &rpc.RemoveRequest{
Workloads: args,
})
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.DisconnectResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
}

106
cmd/kubevpn/cmds/config.go Normal file
View File

@@ -0,0 +1,106 @@
package cmds
import (
"fmt"
"os"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdConfig(f cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "config",
Short: "Proxy kubeconfig which behind of ssh jump server",
}
cmd.AddCommand(cmdConfigAdd(f))
cmd.AddCommand(cmdConfigRemove(f))
return cmd
}
func cmdConfigAdd(f cmdutil.Factory) *cobra.Command {
var sshConf = &pkgssh.SshConfig{}
cmd := &cobra.Command{
Use: "add",
Short: i18n.T("Proxy kubeconfig"),
Long: templates.LongDesc(i18n.T(`proxy kubeconfig which behind of ssh jump server`)),
Example: templates.Examples(i18n.T(`
# proxy api-server which api-server behind of bastion host or ssh jump host
kubevpn config add --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn config add --ssh-alias <alias>
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
// startup daemon process and sudo process
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
req := &rpc.ConfigAddRequest{
KubeconfigBytes: string(bytes),
Namespace: ns,
SshJump: sshConf.ToRPC(),
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
resp, err := cli.ConfigAdd(cmd.Context(), req)
if err != nil {
return err
}
_, _ = fmt.Fprint(os.Stdout, resp.ClusterID)
return nil
},
}
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd
}
func cmdConfigRemove(f cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "remove",
Short: i18n.T("Remove proxy kubeconfig"),
Long: templates.LongDesc(i18n.T(`
Remove proxy kubeconfig which behind of ssh jump server
`)),
Example: templates.Examples(i18n.T(`
# remove proxy api-server which api-server behind of bastion host or ssh jump host
kubevpn config remove --kubeconfig /var/folders/30/cmv9c_5j3mq_kthx63sb1t5c0000gn/T/947048961.kubeconfig
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
// startup daemon process and sudo process
return daemon.StartupDaemon(cmd.Context())
},
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.ExactArgs(1)),
RunE: func(cmd *cobra.Command, args []string) error {
req := &rpc.ConfigRemoveRequest{
ClusterID: args[0],
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
_, err = cli.ConfigRemove(cmd.Context(), req)
if err != nil {
return err
}
return nil
},
}
return cmd
}

View File

@@ -1,64 +1,167 @@
package cmds
import (
"context"
"fmt"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/wencaiwulue/kubevpn/driver"
"github.com/wencaiwulue/kubevpn/pkg"
"github.com/wencaiwulue/kubevpn/util"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/retry"
"os"
"path/filepath"
"syscall"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/utils/ptr"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
"github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl"
)
var connect = pkg.ConnectOptions{}
func CmdConnect(f cmdutil.Factory) *cobra.Command {
var connect = &handler.ConnectOptions{}
var extraRoute = &handler.ExtraRouteInfo{}
var sshConf = &pkgssh.SshConfig{}
var transferImage, foreground, lite bool
var imagePullSecretName string
var managerNamespace string
cmd := &cobra.Command{
Use: "connect",
Short: i18n.T("Connect to kubernetes cluster network"),
Long: templates.LongDesc(i18n.T(`
Connect to kubernetes cluster network
After connect to kubernetes cluster network, you can ping PodIP or
curl ServiceIP in local PC, it also supports k8s DNS resolve.
Like: curl authors/authors.default/authors.default.svc/authors.default.svc.cluster.local.
So you can start up your application in local PC. depends on anything in
k8s cluster is ok, connect to them just like in k8s cluster.
`)),
Example: templates.Examples(i18n.T(`
# Connect to k8s cluster network
kubevpn connect
func init() {
connectCmd.Flags().StringVar(&connect.KubeconfigPath, "kubeconfig", clientcmd.RecommendedHomeFile, "kubeconfig")
connectCmd.Flags().StringVarP(&connect.Namespace, "namespace", "n", "", "namespace")
connectCmd.PersistentFlags().StringArrayVar(&connect.Workloads, "workloads", []string{}, "workloads, like: pods/tomcat, deployment/nginx, replicaset/tomcat...")
connectCmd.Flags().StringVar((*string)(&connect.Mode), "mode", string(pkg.Reverse), "default mode is reverse")
connectCmd.Flags().StringToStringVarP(&connect.Headers, "headers", "H", map[string]string{}, "headers, format is k=v, like: k1=v1,k2=v2")
connectCmd.Flags().BoolVar(&util.Debug, "debug", false, "true/false")
RootCmd.AddCommand(connectCmd)
}
# Connect to api-server behind of bastion host or ssh jump host
kubevpn connect --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
var connectCmd = &cobra.Command{
Use: "connect",
Short: "connect",
Long: `connect`,
PreRun: func(*cobra.Command, []string) {
util.InitLogger(util.Debug)
if util.IsWindows() {
driver.InstallWireGuardTunDriver()
}
},
Run: func(cmd *cobra.Command, args []string) {
if err := connect.InitClient(); err != nil {
log.Fatal(err)
}
connect.PreCheckResource()
if err := connect.DoConnect(); err != nil {
log.Errorln(err)
pkg.Cleanup(syscall.SIGQUIT)
}
select {}
},
PostRun: func(_ *cobra.Command, _ []string) {
if util.IsWindows() {
if err := retry.OnError(retry.DefaultRetry, func(err error) bool {
return err != nil
}, func() error {
return driver.UninstallWireGuardTunDriver()
}); err != nil {
wd, _ := os.Getwd()
filename := filepath.Join(wd, "wintun.dll")
if err = os.Rename(filename, filepath.Join(os.TempDir(), "wintun.dll")); err != nil {
log.Warn(err)
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn connect --ssh-alias <alias>
# Support ssh auth GSSAPI
kubevpn connect --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn connect --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn connect --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
# Support ssh jump inline
kubevpn connect --ssh-jump "--ssh-addr jump.naison.org --ssh-username naison --gssapi-password xxx" --ssh-username root --ssh-addr 127.0.0.1:22 --ssh-keyfile ~/.ssh/dst.pem
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
plog.InitLoggerForClient()
// startup daemon process and sudo process
err := daemon.StartupDaemon(cmd.Context())
if err != nil {
return err
}
if transferImage {
err = regctl.TransferImageWithRegctl(cmd.Context(), config.OriginImage, config.Image)
}
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
if !sshConf.IsEmpty() {
if ip := util.GetAPIServerFromKubeConfigBytes(bytes); ip != nil {
extraRoute.ExtraCIDR = append(extraRoute.ExtraCIDR, ip.String())
}
}
}
},
req := &rpc.ConnectRequest{
KubeconfigBytes: string(bytes),
Namespace: ns,
ExtraRoute: extraRoute.ToRPC(),
Engine: string(connect.Engine),
OriginKubeconfigPath: util.GetKubeConfigPath(f),
SshJump: sshConf.ToRPC(),
TransferImage: transferImage,
Image: config.Image,
ImagePullSecretName: imagePullSecretName,
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
ManagerNamespace: managerNamespace,
}
// if is foreground, send to sudo daemon server
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
var resp grpc.ClientStream
if lite {
resp, err = cli.ConnectFork(cmd.Context(), req)
} else {
resp, err = cli.Connect(cmd.Context(), req)
}
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.ConnectResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
err = disconnect(cli, bytes, ns, sshConf)
return err
}
return err
}
if !foreground {
util.Print(os.Stdout, config.Slogan)
} else {
<-cmd.Context().Done()
err = disconnect(cli, bytes, ns, sshConf)
if err != nil {
return err
}
_, _ = fmt.Fprint(os.Stdout, "Disconnect completed")
}
return nil
},
}
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &connect.Engine)
cmd.Flags().BoolVar(&foreground, "foreground", false, "Hang up")
cmd.Flags().BoolVar(&lite, "lite", false, "connect to multiple cluster in lite mode. mode \"lite\": design for only connecting to multiple cluster network. mode \"full\": not only connect to cluster network, it also supports proxy workloads inbound traffic to local PC.")
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
handler.AddExtraRoute(cmd.Flags(), extraRoute)
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd
}
func disconnect(cli rpc.DaemonClient, bytes []byte, ns string, sshConf *pkgssh.SshConfig) error {
resp, err := cli.Disconnect(context.Background(), &rpc.DisconnectRequest{
KubeconfigBytes: ptr.To(string(bytes)),
Namespace: ptr.To(ns),
SshJump: sshConf.ToRPC(),
})
if err != nil {
plog.G(context.Background()).Errorf("Disconnect error: %v", err)
return err
}
err = util.PrintGRPCStream[rpc.DisconnectResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
}

View File

@@ -0,0 +1,48 @@
package cmds
import (
"context"
"github.com/docker/docker/libnetwork/resolvconf"
miekgdns "github.com/miekg/dns"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/controlplane"
"github.com/wencaiwulue/kubevpn/v2/pkg/dns"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdControlPlane(cmdutil.Factory) *cobra.Command {
var (
watchDirectoryFilename string
port uint = 9002
)
cmd := &cobra.Command{
Use: "control-plane",
Hidden: true,
Short: i18n.T("Control-plane is a envoy xds server"),
Long: templates.LongDesc(i18n.T(`
Control-plane is a envoy xds server, distribute envoy route configuration
`)),
RunE: func(cmd *cobra.Command, args []string) error {
go util.StartupPProfForServer(0)
go func() {
conf, err := miekgdns.ClientConfigFromFile(resolvconf.Path())
if err != nil {
plog.G(context.Background()).Fatal(err)
}
plog.G(context.Background()).Fatal(dns.ListenAndServe("udp", ":53", conf))
}()
err := controlplane.Main(cmd.Context(), watchDirectoryFilename, port, plog.G(context.Background()))
return err
},
}
cmd.Flags().StringVarP(&watchDirectoryFilename, "watchDirectoryFilename", "w", "/etc/envoy/envoy-config.yaml", "full path to directory to watch for files")
cmd.Flags().BoolVar(&config.Debug, "debug", false, "true/false")
return cmd
}

140
cmd/kubevpn/cmds/cp.go Normal file
View File

@@ -0,0 +1,140 @@
package cmds
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericiooptions"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/completion"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/cp"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
)
var cpExample = templates.Examples(i18n.T(`
# !!!Important Note!!!
# Requires that the 'tar' binary is present in your container
# image. If 'tar' is not present, 'kubectl cp' will fail.
#
# For advanced use cases, such as symlinks, wildcard expansion or
# file mode preservation, consider using 'kubectl exec'.
# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace <some-namespace>
tar cf - /tmp/foo | kubectl exec -i -n <some-namespace> <some-pod> -- tar xf - -C /tmp/bar
# Copy /tmp/foo from a remote pod to /tmp/bar locally
kubectl exec -n <some-namespace> <some-pod> -- tar cf - /tmp/foo | tar xf - -C /tmp/bar
# Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the default namespace
kubectl cp /tmp/foo_dir <some-pod>:/tmp/bar_dir
# Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container
kubectl cp /tmp/foo <some-pod>:/tmp/bar -c <specific-container>
# Copy /tmp/foo local file to /tmp/bar in a remote pod in namespace <some-namespace>
kubectl cp /tmp/foo <some-namespace>/<some-pod>:/tmp/bar
# Copy /tmp/foo from a remote pod to /tmp/bar locally
kubectl cp <some-namespace>/<some-pod>:/tmp/foo /tmp/bar
# copy reverse proxy api-server behind of bastion host or ssh jump host
kubevpn cp deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn cp deployment/productpage:/tmp/foo /tmp/bar --ssh-alias <alias>
# Support ssh auth GSSAPI
kubevpn cp deployment/productpage:/tmp/foo /tmp/bar --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn cp deployment/productpage:/tmp/foo /tmp/bar --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn cp deployment/productpage:/tmp/foo /tmp/bar --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
`,
))
func CmdCp(f cmdutil.Factory) *cobra.Command {
o := cp.NewCopyOptions(genericiooptions.IOStreams{
In: os.Stdin,
Out: os.Stdout,
ErrOut: os.Stderr,
})
var sshConf = &pkgssh.SshConfig{}
cmd := &cobra.Command{
Use: "cp <file-spec-src> <file-spec-dest>",
DisableFlagsInUseLine: true,
Hidden: true,
Short: i18n.T("Copy files and directories to and from containers"),
Long: i18n.T("Copy files and directories to and from containers. Different between kubectl cp is it will de-reference symbol link."),
Example: cpExample,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
cmdutil.CheckErr(pkgssh.SshJumpAndSetEnv(cmd.Context(), sshConf, cmd.Flags(), false))
var comps []string
if len(args) == 0 {
if strings.IndexAny(toComplete, "/.~") == 0 {
// Looks like a path, do nothing
} else if strings.Contains(toComplete, ":") {
// TODO: complete remote files in the pod
} else if idx := strings.Index(toComplete, "/"); idx > 0 {
// complete <namespace>/<pod>
namespace := toComplete[:idx]
template := "{{ range .items }}{{ .metadata.namespace }}/{{ .metadata.name }}: {{ end }}"
comps = completion.CompGetFromTemplate(&template, f, namespace, []string{"pod"}, toComplete)
} else {
// Complete namespaces followed by a /
for _, ns := range completion.CompGetResource(f, "namespace", toComplete) {
comps = append(comps, fmt.Sprintf("%s/", ns))
}
// Complete pod names followed by a :
for _, pod := range completion.CompGetResource(f, "pod", toComplete) {
comps = append(comps, fmt.Sprintf("%s:", pod))
}
// Finally, provide file completion if we need to.
// We only do this if:
// 1- There are other completions found (if there are no completions,
// the shell will do file completion itself)
// 2- If there is some input from the user (or else we will end up
// listing the entire content of the current directory which could
// be too many choices for the user)
if len(comps) > 0 && len(toComplete) > 0 {
if files, err := os.ReadDir("."); err == nil {
for _, file := range files {
filename := file.Name()
if strings.HasPrefix(filename, toComplete) {
if file.IsDir() {
filename = fmt.Sprintf("%s/", filename)
}
// We are completing a file prefix
comps = append(comps, filename)
}
}
}
} else if len(toComplete) == 0 {
// If the user didn't provide any input to complete,
// we provide a hint that a path can also be used
comps = append(comps, "./", "/")
}
}
}
return comps, cobra.ShellCompDirectiveNoSpace
},
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.Run())
},
}
cmdutil.AddContainerVarFlags(cmd, &o.Container, o.Container)
cmd.Flags().BoolVarP(&o.NoPreserve, "no-preserve", "", false, "The copied file/directory's ownership and permissions will not be preserved in the container")
cmd.Flags().IntVarP(&o.MaxTries, "retries", "", 0, "Set number of retries to complete a copy operation from a container. Specify 0 to disable or any negative value for infinite retrying. The default is 0 (no retry).")
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd
}

View File

@@ -0,0 +1,89 @@
package cmds
import (
"crypto/rand"
"encoding/base64"
"errors"
"net/http"
"os"
"path/filepath"
"runtime/pprof"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/dns"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdDaemon(cmdutil.Factory) *cobra.Command {
var opt = &daemon.SvrOption{}
cmd := &cobra.Command{
Use: "daemon",
Short: i18n.T("Startup kubevpn daemon server"),
Long: templates.LongDesc(i18n.T(`Startup kubevpn daemon server`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil {
return err
}
opt.ID = base64.URLEncoding.EncodeToString(b)
if opt.IsSudo {
go util.StartupPProf(config.SudoPProfPort)
_ = os.RemoveAll("/etc/resolver")
_ = dns.CleanupHosts()
_ = util.CleanupTempKubeConfigFile()
} else {
go util.StartupPProf(config.PProfPort)
}
return initLogfile(config.GetDaemonLogPath(opt.IsSudo))
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
defer opt.Stop()
defer func() {
if errors.Is(err, http.ErrServerClosed) {
err = nil
}
if opt.IsSudo {
for _, profile := range pprof.Profiles() {
func() {
file, e := os.Create(filepath.Join(config.GetPProfPath(), profile.Name()))
if e != nil {
return
}
defer file.Close()
e = profile.WriteTo(file, 1)
if e != nil {
return
}
}()
}
}
}()
return opt.Start(cmd.Context())
},
Hidden: true,
DisableFlagsInUseLine: true,
}
cmd.Flags().BoolVar(&opt.IsSudo, "sudo", false, "is sudo or not")
return cmd
}
func initLogfile(path string) error {
_, err := os.Lstat(path)
if os.IsNotExist(err) {
var f *os.File
f, err = os.Create(path)
if err != nil {
return err
}
_ = f.Close()
return os.Chmod(path, 0644)
}
return nil
}

156
cmd/kubevpn/cmds/dev.go Normal file
View File

@@ -0,0 +1,156 @@
package cmds
import (
"context"
"fmt"
"os"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/completion"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/dev"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl"
)
func CmdDev(f cmdutil.Factory) *cobra.Command {
var options = &dev.Options{
NoProxy: false,
ExtraRouteInfo: handler.ExtraRouteInfo{},
}
var sshConf = &pkgssh.SshConfig{}
var transferImage bool
var imagePullSecretName string
var managerNamespace string
cmd := &cobra.Command{
Use: "dev TYPE/NAME [-c CONTAINER] [flags] -- [args...]",
Short: i18n.T("Startup your kubernetes workloads in local Docker container"),
Long: templates.LongDesc(i18n.T(`
Startup your kubernetes workloads in local Docker container with same volume、env、and network
## What did it do:
- Download volume which MountPath point to, mount to docker container
- Connect to cluster network, set network to docker container
- Get all environment with command (env), set env to docker container
`)),
Example: templates.Examples(i18n.T(`
# Develop workloads
- develop deployment
kubevpn dev deployment/productpage
- develop service
kubevpn dev service/productpage
# Develop workloads with mesh, traffic with header foo=bar, will hit local PC, otherwise no effect
kubevpn dev service/productpage --headers foo=bar
# Develop workloads without proxy traffic
kubevpn dev service/productpage --no-proxy
# Develop workloads which api-server behind of bastion host or ssh jump host
kubevpn dev deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn dev deployment/productpage --ssh-alias <alias>
# Switch to terminal mode; send stdin to 'bash' and sends stdout/stderror from 'bash' back to the client
kubevpn dev deployment/authors -n default --kubeconfig ~/.kube/config --ssh-alias dev --entrypoint /bin/bash
or
kubevpn dev deployment/authors -n default --kubeconfig ~/.kube/config --ssh-alias dev --entrypoint /bin/bash
# Support ssh auth GSSAPI
kubevpn dev deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab --entrypoint /bin/bash
kubevpn dev deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache --entrypoint /bin/bash
kubevpn dev deployment/authors -n default --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD> --entrypoint /bin/bash
`)),
ValidArgsFunction: completion.ResourceTypeAndNameCompletionFunc(f),
Args: cobra.MatchAll(cobra.OnlyValidArgs),
DisableFlagsInUseLine: true,
PreRunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
_, _ = fmt.Fprintf(os.Stdout, "You must specify the type of resource to proxy. %s\n\n", cmdutil.SuggestAPIResources("kubevpn"))
fullCmdName := cmd.Parent().CommandPath()
usageString := "Required resource not specified."
if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") {
usageString = fmt.Sprintf("%s\nUse \"%s explain <resource>\" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName)
}
return cmdutil.UsageErrorf(cmd, usageString)
}
err := cmd.Flags().Parse(args[1:])
if err != nil {
return err
}
plog.InitLoggerForClient()
err = daemon.StartupDaemon(cmd.Context())
if err != nil {
return err
}
if transferImage {
err = regctl.TransferImageWithRegctl(cmd.Context(), config.OriginImage, config.Image)
}
if err != nil {
return err
}
return pkgssh.SshJumpAndSetEnv(cmd.Context(), sshConf, cmd.Flags(), false)
},
RunE: func(cmd *cobra.Command, args []string) error {
options.Workload = args[0]
for i, arg := range args {
if arg == "--" && i != len(args)-1 {
options.ContainerOptions.Args = args[i+1:]
break
}
}
defer func() {
for _, function := range options.GetRollbackFuncList() {
if function != nil {
if err := function(); err != nil {
plog.G(context.Background()).Errorf("Rollback failed, error: %s", err.Error())
}
}
}
}()
if err := options.InitClient(f); err != nil {
return err
}
conf, hostConfig, err := dev.Parse(cmd.Flags(), options.ContainerOptions)
if err != nil {
return err
}
return options.Main(cmd.Context(), sshConf, conf, hostConfig, imagePullSecretName, managerNamespace)
},
}
cmd.Flags().SortFlags = false
cmd.Flags().StringToStringVarP(&options.Headers, "headers", "H", map[string]string{}, "Traffic with special headers with reverse it to local PC, you should startup your service after reverse workloads successfully, If not special, redirect all traffic to local PC, format is k=v, like: k1=v1,k2=v2")
cmd.Flags().BoolVar(&options.NoProxy, "no-proxy", false, "Whether proxy remote workloads traffic into local or not, true: just startup container on local without inject containers to intercept traffic, false: intercept traffic and forward to local")
cmdutil.AddContainerVarFlags(cmd, &options.ContainerName, options.ContainerName)
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc("container", completion.ContainerCompletionFunc(f)))
cmd.Flags().StringVar((*string)(&options.ConnectMode), "connect-mode", string(dev.ConnectModeHost), "Connect to kubernetes network in container or in host, eg: ["+string(dev.ConnectModeContainer)+"|"+string(dev.ConnectModeHost)+"]")
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &options.Engine)
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
// diy docker options
cmd.Flags().StringVar(&options.DevImage, "dev-image", "", "Use to startup docker container, Default is pod image")
// -- origin docker options -- start
options.ContainerOptions = dev.AddFlags(cmd.Flags())
cmd.Flags().StringVar(&options.RunOptions.Pull, "pull", dev.PullImageMissing, `Pull image before running ("`+dev.PullImageAlways+`"|"`+dev.PullImageMissing+`"|"`+dev.PullImageNever+`")`)
command.AddPlatformFlag(cmd.Flags(), &options.RunOptions.Platform)
// -- origin docker options -- end
handler.AddExtraRoute(cmd.Flags(), &options.ExtraRouteInfo)
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd
}

View File

@@ -0,0 +1,93 @@
package cmds
import (
"fmt"
"os"
"strconv"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/utils/pointer"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdDisconnect(f cmdutil.Factory) *cobra.Command {
var all = false
var clusterIDs []string
cmd := &cobra.Command{
Use: "disconnect",
Short: i18n.T("Disconnect from kubernetes cluster network"),
Long: templates.LongDesc(i18n.T(`
Disconnect from kubernetes cluster network
This command is to disconnect from cluster. after use command 'kubevpn connect',
you can use this command to disconnect from a specific cluster.
before disconnect, it will leave proxy resource and clone resource if resource depends on this cluster
after disconnect it will also cleanup DNS and host
`)),
Example: templates.Examples(i18n.T(`
# disconnect from cluster network and restore proxy resource
kubevpn disconnect
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
plog.InitLoggerForClient()
err = daemon.StartupDaemon(cmd.Context())
return err
},
Args: cobra.MatchAll(cobra.OnlyValidArgs),
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) > 0 && all {
return fmt.Errorf("either specify --all or ID, not both")
}
if len(clusterIDs) > 0 && all {
return fmt.Errorf("either specify --all or cluster-id, not both")
}
if len(args) == 0 && !all && len(clusterIDs) == 0 {
return fmt.Errorf("either specify --all or ID or cluster-id")
}
var ids *int32
if len(args) > 0 {
integer, err := strconv.Atoi(args[0])
if err != nil {
return fmt.Errorf("invalid ID: %s: %v", args[0], err)
}
ids = pointer.Int32(int32(integer))
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
client, err := cli.Disconnect(
cmd.Context(),
&rpc.DisconnectRequest{
ID: ids,
ClusterIDs: clusterIDs,
All: pointer.Bool(all),
},
)
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.DisconnectResponse](client)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
_, _ = fmt.Fprint(os.Stdout, "Disconnect completed")
return nil
},
}
cmd.Flags().BoolVar(&all, "all", all, "Disconnect all cluster, disconnect from all cluster network")
cmd.Flags().StringArrayVar(&clusterIDs, "cluster-id", []string{}, "Cluster id, command status -o yaml/json will show cluster-id")
return cmd
}

113
cmd/kubevpn/cmds/get.go Normal file
View File

@@ -0,0 +1,113 @@
package cmds
import (
"cmp"
"encoding/json"
"os"
"slices"
"strings"
"github.com/spf13/cobra"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/printers"
cmdget "k8s.io/kubectl/pkg/cmd/get"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/scheme"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
)
func CmdGet(f cmdutil.Factory) *cobra.Command {
var printFlags = cmdget.NewGetPrintFlags()
cmd := &cobra.Command{
Use: "get",
Hidden: true,
Short: i18n.T("Get cluster resources which connected"),
Long: templates.LongDesc(i18n.T(`Get cluster resources which connected`)),
Example: templates.Examples(i18n.T(`
# Get resource to k8s cluster network
kubevpn get pods
# Get api-server behind of bastion host or ssh jump host
kubevpn get deployment --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn get service --ssh-alias <alias>
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
// startup daemon process and sudo process
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
ns, _, err := f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
cli, err := daemon.GetClient(true)
if err != nil {
return err
}
client, err := cli.Get(
cmd.Context(),
&rpc.GetRequest{
Namespace: ns,
Resource: args[0],
},
)
if err != nil {
return err
}
w := printers.GetNewTabWriter(os.Stdout)
var toPrinter = func() (printers.ResourcePrinterFunc, error) {
var flags = printFlags.Copy()
_ = flags.EnsureWithNamespace()
printer, err := flags.ToPrinter()
if err != nil {
return nil, err
}
printer, err = printers.NewTypeSetter(scheme.Scheme).WrapToPrinter(printer, nil)
if err != nil {
return nil, err
}
outputOption := cmd.Flags().Lookup("output").Value.String()
if strings.Contains(outputOption, "custom-columns") || outputOption == "yaml" || strings.Contains(outputOption, "json") {
} else {
printer = &cmdget.TablePrinter{Delegate: printer}
}
return printer.PrintObj, nil
}
var list []*v1.PartialObjectMetadata
for _, m := range client.Metadata {
var data v1.PartialObjectMetadata
err = json.Unmarshal([]byte(m), &data)
if err != nil {
continue
}
list = append(list, &data)
}
slices.SortStableFunc(list, func(a, b *v1.PartialObjectMetadata) int {
compare := cmp.Compare(a.GetNamespace(), b.GetNamespace())
if compare == 0 {
return cmp.Compare(a.GetName(), b.GetName())
}
return compare
})
for _, m := range list {
printer, err := toPrinter()
if err != nil {
return err
}
_ = printer.PrintObj(m, w)
}
return w.Flush()
},
}
printFlags.AddFlags(cmd)
return cmd
}

View File

@@ -0,0 +1,43 @@
package cmds
import (
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl"
)
func CmdImageCopy(cmdutil.Factory) *cobra.Command {
var imageCmd = &cobra.Command{
Use: "image <cmd>",
Short: "copy images",
}
copyCmd := &cobra.Command{
Use: "copy <src_image_ref> <dst_image_ref>",
Aliases: []string{"cp"},
Short: "copy or re-tag image",
Long: `Copy or re-tag an image. This works between registries and only pulls layers
that do not exist at the target. In the same registry it attempts to mount
the layers between repositories. And within the same repository it only
sends the manifest with the new tag.`,
Example: `
# copy an image
kubevpn image copy ghcr.io/kubenetworks/kubevpn:latest registry.example.org/kubevpn/kubevpn:latest
# re-tag an image
kubevpn image copy ghcr.io/kubenetworks/kubevpn:latest ghcr.io/kubenetworks/kubevpn:v2.3.4`,
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
PreRunE: func(cmd *cobra.Command, args []string) error {
plog.InitLoggerForClient()
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
err := regctl.TransferImageWithRegctl(cmd.Context(), args[0], args[1])
return err
},
}
imageCmd.AddCommand(copyCmd)
return imageCmd
}

64
cmd/kubevpn/cmds/leave.go Normal file
View File

@@ -0,0 +1,64 @@
package cmds
import (
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdLeave(f cmdutil.Factory) *cobra.Command {
var leaveCmd = &cobra.Command{
Use: "leave",
Short: i18n.T("Leave proxy resource"),
Long: templates.LongDesc(i18n.T(`
Leave proxy resource and restore it to origin
This command is used to leave proxy resources. after use command 'kubevpn proxy xxx',
you can use this command to leave proxy resources.
you can just leave proxy resources which do proxy by yourself.
and the last one leave proxy resource, it will also restore workloads container.
otherwise it will keep containers [vpn, envoy-proxy] until last one to leave.
`)),
Example: templates.Examples(i18n.T(`
# leave proxy resource and restore it to origin
kubevpn leave deployment/authors
`)),
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
_, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
resp, err := cli.Leave(cmd.Context(), &rpc.LeaveRequest{
Namespace: ns,
Workloads: args,
})
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.LeaveResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
},
}
return leaveCmd
}

45
cmd/kubevpn/cmds/list.go Normal file
View File

@@ -0,0 +1,45 @@
package cmds
import (
"fmt"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
)
func CmdList(f cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: i18n.T("List proxy resources"),
Long: templates.LongDesc(i18n.T(`List proxy resources`)),
Example: templates.Examples(i18n.T(`
# list proxy resources
kubevpn list
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
cli, err := daemon.GetClient(true)
if err != nil {
return err
}
client, err := cli.List(
cmd.Context(),
&rpc.ListRequest{},
)
if err != nil {
return err
}
fmt.Println(client.GetMessage())
return nil
},
Hidden: true,
}
return cmd
}

58
cmd/kubevpn/cmds/logs.go Normal file
View File

@@ -0,0 +1,58 @@
package cmds
import (
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdLogs(f cmdutil.Factory) *cobra.Command {
req := &rpc.LogRequest{}
cmd := &cobra.Command{
Use: "logs",
Short: i18n.T("Log kubevpn daemon grpc server"),
Long: templates.LongDesc(i18n.T(`
Print the logs for kubevpn daemon grpc server. it will show sudo daemon and daemon grpc server log in both
`)),
Example: templates.Examples(i18n.T(`
# show log for kubevpn daemon server
kubevpn logs
# follow more log
kubevpn logs -f
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
plog.InitLoggerForClient()
// startup daemon process and sudo process
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
cli, err := daemon.GetClient(true)
if err != nil {
return err
}
client, err := cli.Logs(cmd.Context(), req)
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.LogResponse](client)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
},
}
cmd.Flags().BoolVarP(&req.Follow, "follow", "f", false, "Specify if the logs should be streamed.")
cmd.Flags().Int32VarP(&req.Lines, "number", "N", 10, "Lines of recent log file to display.")
return cmd
}

View File

@@ -0,0 +1,36 @@
package cmds
import (
"os"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
var (
optionsExample = templates.Examples(i18n.T(`
# Print flags inherited by all commands
kubevpn options
`))
)
func CmdOptions(cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "options",
Short: i18n.T("Print the list of flags inherited by all commands"),
Long: templates.LongDesc(i18n.T(`
Print the list of flags inherited by all commands
`)),
Example: optionsExample,
Run: func(cmd *cobra.Command, args []string) {
cmd.Usage()
},
}
cmd.SetOut(os.Stdout)
templates.UseOptionsTemplates(cmd)
return cmd
}

191
cmd/kubevpn/cmds/proxy.go Normal file
View File

@@ -0,0 +1,191 @@
package cmds
import (
"context"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
utilcomp "k8s.io/kubectl/pkg/util/completion"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
"github.com/wencaiwulue/kubevpn/v2/pkg/util/regctl"
)
func CmdProxy(f cmdutil.Factory) *cobra.Command {
var headers = make(map[string]string)
var portmap []string
var connect = handler.ConnectOptions{}
var extraRoute = &handler.ExtraRouteInfo{}
var sshConf = &pkgssh.SshConfig{}
var transferImage, foreground bool
var imagePullSecretName string
var managerNamespace string
cmd := &cobra.Command{
Use: "proxy",
Short: i18n.T("Proxy kubernetes workloads inbound traffic into local PC"),
Long: templates.LongDesc(i18n.T(`
Proxy kubernetes workloads inbound traffic into local PC
Proxy k8s workloads inbound traffic into local PC with/without service mesh.
Without service mesh, it will proxy all inbound traffic into local PC, even traffic protocol is layer 4(Transport layer).
With service mesh, it will proxy traffic which has special header to local PC, support protocol HTTP,GRPC,THRIFT, WebSocket...
After proxy resource, it also connected to cluster network automatically. so just startup your app in local PC
and waiting for inbound traffic, make debug more easier.
`)),
Example: templates.Examples(i18n.T(`
# Reverse proxy
- proxy deployment
kubevpn proxy deployment/productpage
- proxy service
kubevpn proxy service/productpage
- proxy multiple workloads
kubevpn proxy deployment/authors deployment/productpage
or
kubevpn proxy deployment authors productpage
# Reverse proxy with mesh, traffic with header foo=bar, will hit local PC, otherwise no effect
kubevpn proxy service/productpage --headers foo=bar
# Reverse proxy with mesh, traffic with header foo=bar and env=dev, will hit local PC, otherwise no effect
kubevpn proxy service/productpage --headers foo=bar --headers env=dev
# Connect to api-server behind of bastion host or ssh jump host and proxy kubernetes resource traffic into local PC
kubevpn proxy deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem --headers foo=bar
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn proxy service/productpage --ssh-alias <alias> --headers foo=bar
# Support ssh auth GSSAPI
kubevpn proxy service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn proxy service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn proxy service/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
# Support port map, you can proxy container port to local port by command:
kubevpn proxy deployment/productpage --portmap 80:8080
# Proxy container port 9080 to local port 8080 of TCP protocol
kubevpn proxy deployment/productpage --portmap 9080:8080
# Proxy container port 9080 to local port 5000 of UDP protocol
kubevpn proxy deployment/productpage --portmap udp/9080:5000
# Auto proxy container port to same local port, and auto detect protocol
kubevpn proxy deployment/productpage
`)),
Args: cobra.MatchAll(cobra.OnlyValidArgs, cobra.MinimumNArgs(1)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
plog.InitLoggerForClient()
if err = daemon.StartupDaemon(cmd.Context()); err != nil {
return err
}
if transferImage {
err = regctl.TransferImageWithRegctl(cmd.Context(), config.OriginImage, config.Image)
}
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
if !sshConf.IsEmpty() {
if ip := util.GetAPIServerFromKubeConfigBytes(bytes); ip != nil {
extraRoute.ExtraCIDR = append(extraRoute.ExtraCIDR, ip.String())
}
}
// todo 将 doConnect 方法封装?内部使用 client 发送到daemon
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
resp, err := cli.Proxy(
cmd.Context(),
&rpc.ProxyRequest{
KubeconfigBytes: string(bytes),
Namespace: ns,
Headers: headers,
PortMap: portmap,
Workloads: args,
ExtraRoute: extraRoute.ToRPC(),
Engine: string(connect.Engine),
SshJump: sshConf.ToRPC(),
TransferImage: transferImage,
Image: config.Image,
ImagePullSecretName: imagePullSecretName,
Level: int32(util.If(config.Debug, log.DebugLevel, log.InfoLevel)),
OriginKubeconfigPath: util.GetKubeConfigPath(f),
ManagerNamespace: managerNamespace,
},
)
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.ConnectResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
err = leave(cli, ns, args)
return err
}
return err
}
util.Print(os.Stdout, config.Slogan)
// hangup
if foreground {
// leave from cluster resources
<-cmd.Context().Done()
err = leave(cli, ns, args)
if err != nil {
return err
}
}
return nil
},
}
cmd.Flags().StringToStringVarP(&headers, "headers", "H", map[string]string{}, "Traffic with special headers (use `and` to match all headers) with reverse it to local PC, If not special, redirect all traffic to local PC. format: <KEY>=<VALUE> eg: --headers foo=bar --headers env=dev")
cmd.Flags().StringArrayVar(&portmap, "portmap", []string{}, "Port map, map container port to local port, format: [tcp/udp]/containerPort:localPort, If not special, localPort will use containerPort. eg: tcp/80:8080 or udp/5000:5001 or 80 or 80:8080")
handler.AddCommonFlags(cmd.Flags(), &transferImage, &imagePullSecretName, &connect.Engine)
cmd.Flags().BoolVar(&foreground, "foreground", false, "foreground hang up")
cmd.Flags().StringVar(&managerNamespace, "manager-namespace", "", "The namespace where the traffic manager is to be found. Only works in cluster mode (install kubevpn server by helm)")
handler.AddExtraRoute(cmd.Flags(), extraRoute)
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
cmd.ValidArgsFunction = utilcomp.ResourceTypeAndNameCompletionFunc(f)
return cmd
}
func leave(cli rpc.DaemonClient, ns string, args []string) error {
stream, err := cli.Leave(context.Background(), &rpc.LeaveRequest{
Namespace: ns,
Workloads: args,
})
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.LeaveResponse](stream)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
}

59
cmd/kubevpn/cmds/quit.go Normal file
View File

@@ -0,0 +1,59 @@
package cmds
import (
"context"
"fmt"
"os"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdQuit(f cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "quit",
Short: i18n.T("Quit kubevpn daemon grpc server"),
Long: templates.LongDesc(i18n.T(`
Disconnect from cluster, leave proxy resources, quit daemon grpc server and cleanup dns/hosts
`)),
Example: templates.Examples(i18n.T(`
# before quit kubevpn, it will leave proxy resources to origin and disconnect from cluster
kubevpn quit
`)),
RunE: func(cmd *cobra.Command, args []string) error {
_ = quit(cmd.Context(), true)
_ = quit(cmd.Context(), false)
util.CleanExtensionLib()
_, _ = fmt.Fprint(os.Stdout, "Exited")
return nil
},
}
return cmd
}
func quit(ctx context.Context, isSudo bool) error {
cli, err := daemon.GetClient(isSudo)
if err != nil {
return err
}
client, err := cli.Quit(ctx, &rpc.QuitRequest{})
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.QuitResponse](client)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
}

View File

@@ -0,0 +1,56 @@
package cmds
import (
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdRemove(f cmdutil.Factory) *cobra.Command {
var cmd = &cobra.Command{
Use: "remove",
Short: "Remove clone resource",
Long: templates.LongDesc(i18n.T(`
Remove clone resource
This command is design to remove clone resources, after use command 'kubevpn clone xxx',
it will generate and create a new resource in target k8s cluster with format [resource_name]_clone_xxxxx,
use this command to remove this created resources.
`)),
Example: templates.Examples(i18n.T(`
# leave proxy resources to origin
kubevpn remove deployment/authors-clone-645d7
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
resp, err := cli.Remove(cmd.Context(), &rpc.RemoveRequest{
Workloads: args,
})
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.RemoveResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
},
}
return cmd
}

86
cmd/kubevpn/cmds/reset.go Normal file
View File

@@ -0,0 +1,86 @@
package cmds
import (
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdReset(f cmdutil.Factory) *cobra.Command {
var sshConf = &pkgssh.SshConfig{}
cmd := &cobra.Command{
Use: "reset",
Short: "Reset workloads to origin status",
Long: templates.LongDesc(i18n.T(`
Reset workloads to origin status
Reset will remove injected container envoy-proxy and vpn, and restore service mesh rules.
`)),
Example: templates.Examples(i18n.T(`
# Reset default namespace workloads depooyment/productpage
kubevpn reset deployment/productpage
# Reset another namespace test workloads depooyment/productpage
kubevpn reset deployment/productpage -n test
# Reset workloads depooyment/productpage which api-server behind of bastion host or ssh jump host
kubevpn reset deployment/productpage --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn reset deployment/productpage --ssh-alias <alias>
# Support ssh auth GSSAPI
kubevpn reset deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn reset deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn reset deployment/productpage --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
plog.InitLoggerForClient()
return daemon.StartupDaemon(cmd.Context())
},
Args: cobra.MatchAll(cobra.ExactArgs(1)),
RunE: func(cmd *cobra.Command, args []string) error {
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
req := &rpc.ResetRequest{
KubeconfigBytes: string(bytes),
Namespace: ns,
Workloads: args,
SshJump: sshConf.ToRPC(),
}
resp, err := cli.Reset(cmd.Context(), req)
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.ResetResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
},
}
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd
}

View File

@@ -1,9 +1,112 @@
package cmds
import "github.com/spf13/cobra"
import (
"os"
"strings"
var RootCmd = &cobra.Command{
Use: "kubevpn",
Short: "kubevpn",
Long: `kubevpn`,
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/utils/ptr"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
)
func NewKubeVPNCommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "kubevpn",
Short: i18n.T("KubeVPN offers a Cloud-Native Dev Environment that seamlessly connects to your Kubernetes cluster network."),
Long: templates.LongDesc(`
KubeVPN offers a Cloud-Native Dev Environment that seamlessly connects to your Kubernetes cluster network.
`),
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
flags := cmd.PersistentFlags()
configFlags := genericclioptions.NewConfigFlags(true)
configFlags.WrapConfigFn = func(c *rest.Config) *rest.Config {
if path, ok := os.LookupEnv(config.EnvSSHJump); ok {
kubeconfigBytes, err := os.ReadFile(path)
cmdutil.CheckErr(err)
var conf *restclient.Config
conf, err = clientcmd.RESTConfigFromKubeConfig(kubeconfigBytes)
cmdutil.CheckErr(err)
return conf
}
return c
}
configFlags.AddFlags(flags)
matchVersionFlags := cmdutil.NewMatchVersionFlags(&warp{ConfigFlags: configFlags})
matchVersionFlags.AddFlags(flags)
factory := cmdutil.NewFactory(matchVersionFlags)
groups := templates.CommandGroups{
{
Message: "Develop commands:",
Commands: []*cobra.Command{
CmdConnect(factory),
CmdDisconnect(factory),
CmdProxy(factory),
CmdLeave(factory),
CmdClone(factory),
CmdRemove(factory),
CmdDev(factory),
// Hidden, Server Commands (DO NOT USE IT !!!)
CmdControlPlane(factory),
CmdServer(factory),
CmdDaemon(factory),
CmdWebhook(factory),
CmdSyncthing(factory),
},
},
{
Message: "Management commands:",
Commands: []*cobra.Command{
CmdStatus(factory),
CmdList(factory),
CmdAlias(factory),
CmdGet(factory),
CmdConfig(factory),
CmdSSH(factory),
CmdSSHDaemon(factory),
CmdImageCopy(factory),
CmdLogs(factory),
CmdCp(factory),
CmdReset(factory),
CmdUninstall(factory),
CmdQuit(factory),
},
},
{
Message: "Other commands:",
Commands: []*cobra.Command{
CmdUpgrade(factory),
CmdVersion(factory),
},
},
}
groups.Add(cmd)
templates.ActsAsRootCommand(cmd, []string{"options"}, groups...)
cmd.AddCommand(CmdOptions(factory))
return cmd
}
type warp struct {
*genericclioptions.ConfigFlags
}
func (f *warp) ToRawKubeConfigLoader() clientcmd.ClientConfig {
if strings.HasPrefix(ptr.Deref[string](f.KubeConfig, ""), "~") {
home := homedir.HomeDir()
f.KubeConfig = ptr.To(strings.Replace(*f.KubeConfig, "~", home, 1))
}
return f.ConfigFlags.ToRawKubeConfigLoader()
}

View File

@@ -1,33 +0,0 @@
package cmds
import (
"context"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/wencaiwulue/kubevpn/pkg"
"github.com/wencaiwulue/kubevpn/util"
)
var config pkg.Route
func init() {
ServerCmd.Flags().StringArrayVarP(&config.ServeNodes, "nodeCommand", "L", []string{}, "command needs to be executed")
ServerCmd.Flags().StringVarP(&config.ChainNode, "chainCommand", "F", "", "command needs to be executed")
ServerCmd.Flags().BoolVar(&util.Debug, "debug", false, "true/false")
RootCmd.AddCommand(ServerCmd)
}
var ServerCmd = &cobra.Command{
Use: "serve",
Short: "serve",
Long: `serve`,
PreRun: func(*cobra.Command, []string) {
util.InitLogger(util.Debug)
},
Run: func(cmd *cobra.Command, args []string) {
if err := pkg.Start(context.TODO(), config); err != nil {
log.Fatal(err)
}
select {}
},
}

View File

@@ -0,0 +1,60 @@
package cmds
import (
"math/rand"
"os"
"runtime"
"time"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"go.uber.org/automaxprocs/maxprocs"
glog "gvisor.dev/gvisor/pkg/log"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/core"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdServer(cmdutil.Factory) *cobra.Command {
var route = &core.Route{}
cmd := &cobra.Command{
Use: "server",
Hidden: true,
Short: "Server side, startup traffic manager, forward inbound and outbound traffic",
Long: templates.LongDesc(i18n.T(`
Server side, startup traffic manager, forward inbound and outbound traffic.
`)),
Example: templates.Examples(i18n.T(`
# server listener
kubevpn server -l "tcp://:10800" -l "tun://127.0.0.1:8422?net=198.19.0.123/32"
`)),
PreRun: func(*cobra.Command, []string) {
runtime.GOMAXPROCS(0)
go util.StartupPProfForServer(config.PProfPort)
glog.SetTarget(plog.ServerEmitter{Writer: &glog.Writer{Next: os.Stderr}})
},
RunE: func(cmd *cobra.Command, args []string) error {
rand.Seed(time.Now().UnixNano())
_, _ = maxprocs.Set(maxprocs.Logger(nil))
ctx := cmd.Context()
logger := plog.InitLoggerForServer()
logger.SetLevel(util.If(config.Debug, log.DebugLevel, log.InfoLevel))
servers, err := handler.Parse(*route)
if err != nil {
plog.G(ctx).Errorf("Parse server failed: %v", err)
return err
}
return handler.Run(plog.WithLogger(ctx, logger), servers)
},
}
cmd.Flags().StringArrayVarP(&route.Listeners, "listener", "l", []string{}, "Startup listener server. eg: tcp://localhost:1080")
cmd.Flags().StringVarP(&route.Forwarder, "forwarder", "f", "", "Special forwarder. eg: tcp://192.168.1.100:2345")
cmd.Flags().BoolVar(&config.Debug, "debug", false, "Enable debug log or not")
return cmd
}

195
cmd/kubevpn/cmds/ssh.go Normal file
View File

@@ -0,0 +1,195 @@
package cmds
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"github.com/containerd/containerd/platforms"
"github.com/google/uuid"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/net/websocket"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
// CmdSSH
// Remember to use network mask 32, because ssh using unique network CIDR 198.18.0.0/16
func CmdSSH(cmdutil.Factory) *cobra.Command {
var sshConf = &pkgssh.SshConfig{}
var extraCIDR []string
var platform string
var lite bool
cmd := &cobra.Command{
Use: "ssh",
Short: "Ssh to jump server",
Long: templates.LongDesc(i18n.T(`
Ssh to jump server
`)),
Example: templates.Examples(i18n.T(`
# Jump to server behind of bastion host or ssh jump host
kubevpn ssh --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────┘
kubevpn ssh --ssh-alias <alias>
# Support ssh auth GSSAPI
kubevpn ssh --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn ssh --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn ssh --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
plog.InitLoggerForClient()
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
plat, err := platforms.Parse(platform)
if err != nil {
return err
}
config, err := websocket.NewConfig("ws://test/ws", "http://test")
if err != nil {
return err
}
fd := int(os.Stdin.Fd())
if !terminal.IsTerminal(fd) {
return fmt.Errorf("stdin is not a terminal")
}
width, height, err := terminal.GetSize(fd)
if err != nil {
return fmt.Errorf("terminal get size: %s", err)
}
sessionID := uuid.NewString()
ssh := handler.Ssh{
Config: *sshConf,
ExtraCIDR: extraCIDR,
Width: width,
Height: height,
Platform: platforms.Format(platforms.Normalize(plat)),
SessionID: sessionID,
Lite: lite,
}
marshal, err := json.Marshal(ssh)
if err != nil {
return err
}
config.Header.Set("ssh", string(marshal))
client := daemon.GetTCPClient(true)
if client == nil {
return fmt.Errorf("client is nil")
}
conn, err := websocket.NewClient(config, client)
if err != nil {
return err
}
defer conn.Close()
errChan := make(chan error, 3)
go func() {
errChan <- monitorSize(cmd.Context(), sessionID)
}()
readyCtx, cancelFunc := context.WithCancel(cmd.Context())
checker := func(log string) bool {
isReady := strings.Contains(log, fmt.Sprintf(handler.SshTerminalReadyFormat, sessionID))
if isReady {
cancelFunc()
}
return isReady
}
var state *terminal.State
go func() {
select {
case <-cmd.Context().Done():
return
case <-readyCtx.Done():
}
if state, err = terminal.MakeRaw(fd); err != nil {
plog.G(context.Background()).Errorf("terminal make raw: %s", err)
}
}()
go func() {
_, err := io.Copy(conn, os.Stdin)
errChan <- err
}()
go func() {
_, err := io.Copy(io.MultiWriter(os.Stdout, util.NewWriter(checker)), conn)
errChan <- err
}()
defer func() {
if state != nil {
terminal.Restore(fd, state)
}
}()
select {
case err := <-errChan:
return err
case <-cmd.Context().Done():
return cmd.Context().Err()
}
},
}
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
cmd.Flags().StringArrayVar(&extraCIDR, "extra-cidr", []string{}, "Extra network CIDR string, eg: --extra-cidr 192.168.0.159/24 --extra-cidr 192.168.1.160/32")
cmd.Flags().StringVar(&platform, "platform", util.If(os.Getenv("KUBEVPN_DEFAULT_PLATFORM") != "", os.Getenv("KUBEVPN_DEFAULT_PLATFORM"), "linux/amd64"), "Set ssh server platform if needs to install command kubevpn")
cmd.Flags().BoolVar(&lite, "lite", false, "connect to ssh server in lite mode. mode \"lite\": design for only connect to ssh server. mode \"full\": not only connect to ssh server, it also create a two-way tunnel communicate with inner ip")
return cmd
}
func monitorSize(ctx context.Context, sessionID string) error {
conn := daemon.GetTCPClient(true)
if conn == nil {
return fmt.Errorf("conn is nil")
}
var tt = term.TTY{
In: os.Stdin,
Out: os.Stdout,
Raw: false,
TryDev: false,
Parent: nil,
}
sizeQueue := tt.MonitorSize(tt.GetSize())
if sizeQueue == nil {
return fmt.Errorf("sizeQueue is nil")
}
//defer runtime.HandleCrash()
config, err := websocket.NewConfig("ws://test/resize", "http://test")
if err != nil {
return err
}
config.Header.Set("session-id", sessionID)
client, err := websocket.NewClient(config, conn)
if err != nil {
return err
}
encoder := json.NewEncoder(client)
for ctx.Err() == nil {
size := sizeQueue.Next()
if size == nil {
return nil
}
if err = encoder.Encode(&size); err != nil {
plog.G(ctx).Errorf("Encode resize: %s", err)
return err
}
}
return nil
}

View File

@@ -0,0 +1,53 @@
package cmds
import (
"fmt"
"os"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
)
// CmdSSHDaemon
// set local tun ip 198.19.0.1/32, remember to use mask 32
func CmdSSHDaemon(cmdutil.Factory) *cobra.Command {
var clientIP string
cmd := &cobra.Command{
Use: "ssh-daemon",
Hidden: true,
Short: "Ssh daemon server",
Long: templates.LongDesc(i18n.T(`Ssh daemon server`)),
Example: templates.Examples(i18n.T(`
# SSH daemon server
kubevpn ssh-daemon --client-ip 198.19.0.123/32
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
err := daemon.StartupDaemon(cmd.Context())
return err
},
RunE: func(cmd *cobra.Command, args []string) error {
cli, err := daemon.GetClient(true)
if err != nil {
return err
}
resp, err := cli.SshStart(
cmd.Context(),
&rpc.SshStartRequest{
ClientIP: clientIP,
},
)
if err != nil {
return err
}
_, err = fmt.Fprint(os.Stdout, resp.ServerIP)
return err
},
}
cmd.Flags().StringVar(&clientIP, "client-ip", "", "Client cidr")
return cmd
}

287
cmd/kubevpn/cmds/status.go Normal file
View File

@@ -0,0 +1,287 @@
package cmds
import (
"bytes"
"encoding/json"
"fmt"
"os"
"strings"
"github.com/liggitt/tabwriter"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"sigs.k8s.io/yaml"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
const (
FormatJson = "json"
FormatYaml = "yaml"
FormatTable = "table"
)
func CmdStatus(f cmdutil.Factory) *cobra.Command {
var aliasName string
var localFile string
var remoteAddr string
var format string
cmd := &cobra.Command{
Use: "status",
Short: i18n.T("Show connect status and list proxy/clone resource"),
Long: templates.LongDesc(i18n.T(`
Show connect status and list proxy/clone resource
Show connect status and list proxy or clone resource, you can check connect status by filed status and netif.
if netif is empty, means tun device closed, so it's unhealthy, it will also show route info, if proxy workloads,
not only show myself proxy resource, another route info will also display.
`)),
Example: templates.Examples(i18n.T(`
# show status for connect status and list proxy/clone resource
kubevpn status
# query status by alias config name dev_new
kubevpn status --alias dev_new
# query status with output json format
kubevpn status -o json
# query status with output yaml format
kubevpn status -o yaml
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
plog.InitLoggerForClient()
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
var clusterIDs []string
if aliasName != "" {
configs, err := ParseAndGet(localFile, remoteAddr, aliasName)
if err != nil {
return err
}
for _, conf := range configs {
clusterID, err := GetClusterIDByConfig(cmd, conf)
if err != nil {
return err
}
clusterIDs = append(clusterIDs, clusterID)
}
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
resp, err := cli.Status(
cmd.Context(),
&rpc.StatusRequest{
ClusterIDs: clusterIDs,
},
)
if err != nil {
return err
}
output, err := genOutput(resp, format)
if err != nil {
return err
}
_, _ = fmt.Fprint(os.Stdout, output)
return nil
},
}
cmd.Flags().StringVar(&aliasName, "alias", "", "Alias name, query connect status by alias config name")
cmd.Flags().StringVarP(&localFile, "kubevpnconfig", "f", util.If(os.Getenv("KUBEVPNCONFIG") != "", os.Getenv("KUBEVPNCONFIG"), config.GetConfigFile()), "Path to the kubevpnconfig file to use for CLI requests.")
cmd.Flags().StringVarP(&remoteAddr, "remote", "r", "", "Remote config file, eg: https://raw.githubusercontent.com/kubenetworks/kubevpn/master/pkg/config/config.yaml")
cmd.Flags().StringVarP(&format, "output", "o", FormatTable, fmt.Sprintf("Output format. One of: (%s, %s, %s)", FormatJson, FormatYaml, FormatTable))
return cmd
}
func genOutput(status *rpc.StatusResponse, format string) (string, error) {
switch format {
case FormatJson:
if len(status.List) == 0 {
return "", nil
}
marshal, err := json.Marshal(status.List)
if err != nil {
return "", err
}
return string(marshal), nil
case FormatYaml:
if len(status.List) == 0 {
return "", nil
}
marshal, err := yaml.Marshal(status.List)
if err != nil {
return "", err
}
return string(marshal), nil
default:
var sb = new(bytes.Buffer)
w := printers.GetNewTabWriter(sb)
genConnectMsg(w, status.List)
genProxyMsg(w, status.List)
genCloneMsg(w, status.List)
_ = w.Flush()
return sb.String(), nil
}
}
func genConnectMsg(w *tabwriter.Writer, status []*rpc.Status) {
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", "ID", "Mode", "Cluster", "Kubeconfig", "Namespace", "Status", "Netif")
for _, c := range status {
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%s\n", c.ID, c.Mode, c.Cluster, c.Kubeconfig, c.Namespace, c.Status, c.Netif)
}
}
func genProxyMsg(w *tabwriter.Writer, list []*rpc.Status) {
var needsPrint bool
for _, status := range list {
if len(status.ProxyList) != 0 {
needsPrint = true
break
}
}
if !needsPrint {
return
}
_, _ = fmt.Fprintf(w, "\n")
w.SetRememberedWidths(nil)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", "ID", "Namespace", "Name", "Headers", "IP", "PortMap", "CurrentPC")
for _, c := range list {
for _, proxy := range c.ProxyList {
for _, rule := range proxy.RuleList {
var headers []string
for k, v := range rule.Headers {
headers = append(headers, fmt.Sprintf("%s=%s", k, v))
}
if len(headers) == 0 {
headers = []string{"*"}
}
var portmap []string
for k, v := range rule.PortMap {
portmap = append(portmap, fmt.Sprintf("%d->%d", k, v))
}
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\t%v\n",
c.ID,
proxy.Namespace,
proxy.Workload,
strings.Join(headers, ","),
rule.LocalTunIPv4,
strings.Join(portmap, ","),
rule.CurrentDevice,
)
}
}
}
}
func genCloneMsg(w *tabwriter.Writer, list []*rpc.Status) {
var needsPrint bool
for _, status := range list {
if len(status.CloneList) != 0 {
needsPrint = true
break
}
}
if !needsPrint {
return
}
_, _ = fmt.Fprintf(w, "\n")
w.SetRememberedWidths(nil)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n", "ID", "Namespace", "Name", "Headers", "ToName", "SyncthingGUI")
for _, c := range list {
for _, clone := range c.CloneList {
//_, _ = fmt.Fprintf(w, "%s\n", clone.Workload)
for _, rule := range clone.RuleList {
var headers []string
for k, v := range rule.Headers {
headers = append(headers, fmt.Sprintf("%s=%s", k, v))
}
if len(headers) == 0 {
headers = []string{"*"}
}
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\n",
c.ID,
clone.Namespace,
clone.Workload,
strings.Join(headers, ","),
rule.DstWorkload,
clone.SyncthingGUIAddr,
)
}
}
}
}
func GetClusterIDByConfig(cmd *cobra.Command, config Config) (string, error) {
flags := flag.NewFlagSet("", flag.ContinueOnError)
var sshConf = &pkgssh.SshConfig{}
pkgssh.AddSshFlags(flags, sshConf)
handler.AddExtraRoute(flags, &handler.ExtraRouteInfo{})
configFlags := genericclioptions.NewConfigFlags(true)
configFlags.AddFlags(flags)
matchVersionFlags := cmdutil.NewMatchVersionFlags(&warp{ConfigFlags: configFlags})
matchVersionFlags.AddFlags(flags)
factory := cmdutil.NewFactory(matchVersionFlags)
for _, command := range cmd.Parent().Commands() {
command.Flags().VisitAll(func(f *flag.Flag) {
if flags.Lookup(f.Name) == nil && flags.ShorthandLookup(f.Shorthand) == nil {
flags.AddFlag(f)
}
})
}
err := flags.ParseAll(config.Flags, func(flag *flag.Flag, value string) error {
_ = flags.Set(flag.Name, value)
return nil
})
bytes, ns, err := util.ConvertToKubeConfigBytes(factory)
if err != nil {
return "", err
}
file, err := util.ConvertToTempKubeconfigFile(bytes)
if err != nil {
return "", err
}
flags = flag.NewFlagSet("", flag.ContinueOnError)
flags.AddFlag(&flag.Flag{
Name: "kubeconfig",
DefValue: file,
})
flags.AddFlag(&flag.Flag{
Name: "namespace",
DefValue: ns,
})
var path string
path, err = pkgssh.SshJump(cmd.Context(), sshConf, flags, false)
if err != nil {
return "", err
}
var c = &handler.ConnectOptions{}
err = c.InitClient(util.InitFactoryByPath(path, ns))
if err != nil {
return "", err
}
err = c.InitDHCP(cmd.Context())
if err != nil {
return "", err
}
return c.GetClusterID(), nil
}

View File

@@ -0,0 +1,218 @@
package cmds
import (
"fmt"
"testing"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
)
func TestPrintProxyAndClone(t *testing.T) {
var status = &rpc.StatusResponse{
List: []*rpc.Status{
{
ID: 0,
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun4",
ProxyList: []*rpc.Proxy{
{
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Workload: "deployment.apps/authors",
RuleList: []*rpc.ProxyRule{
{
Headers: map[string]string{"user": "naison"},
LocalTunIPv4: "198.19.0.103",
LocalTunIPv6: "2001:2::999d",
CurrentDevice: false,
PortMap: map[int32]int32{8910: 8910},
},
},
},
},
CloneList: []*rpc.Clone{
{
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Workload: "deployment.apps/ratings",
RuleList: []*rpc.CloneRule{{
Headers: map[string]string{"user": "naison"},
DstClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
DstCluster: "ccm6epn7qvcplhs3o8p00",
DstKubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
DstNamespace: "vke-system",
DstWorkload: "deployment.apps/ratings-clone-5ngn6",
}},
},
},
},
{
ID: 1,
ClusterID: "c08cae70-0021-46c9-a1dc-38e6a2f11443",
Cluster: "ccnepblsebp68ivej4a20",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/dev_fy_config_new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun5",
ProxyList: []*rpc.Proxy{},
CloneList: []*rpc.Clone{},
},
},
}
output, err := genOutput(status, FormatTable)
if err != nil {
t.Fatal(err)
}
fmt.Println(output)
}
func TestPrintProxy(t *testing.T) {
var status = &rpc.StatusResponse{
List: []*rpc.Status{
{
ID: 0,
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun4",
ProxyList: []*rpc.Proxy{
{
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Workload: "deployment.apps/authors",
RuleList: []*rpc.ProxyRule{
{
Headers: map[string]string{"user": "naison"},
LocalTunIPv4: "198.19.0.103",
LocalTunIPv6: "2001:2::999d",
CurrentDevice: false,
PortMap: map[int32]int32{8910: 8910},
},
},
},
},
CloneList: []*rpc.Clone{},
},
{
ID: 1,
ClusterID: "c08cae70-0021-46c9-a1dc-38e6a2f11443",
Cluster: "ccnepblsebp68ivej4a20",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/dev_fy_config_new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun5",
ProxyList: []*rpc.Proxy{},
CloneList: []*rpc.Clone{},
},
},
}
output, err := genOutput(status, FormatTable)
if err != nil {
t.Fatal(err)
}
fmt.Println(output)
}
func TestPrintClone(t *testing.T) {
var status = &rpc.StatusResponse{
List: []*rpc.Status{
{
ID: 0,
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun4",
ProxyList: []*rpc.Proxy{},
CloneList: []*rpc.Clone{
{
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Workload: "deployment.apps/ratings",
RuleList: []*rpc.CloneRule{{
Headers: map[string]string{"user": "naison"},
DstClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
DstCluster: "ccm6epn7qvcplhs3o8p00",
DstKubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
DstNamespace: "vke-system",
DstWorkload: "deployment.apps/ratings-clone-5ngn6",
}},
},
},
},
{
ID: 1,
ClusterID: "c08cae70-0021-46c9-a1dc-38e6a2f11443",
Cluster: "ccnepblsebp68ivej4a20",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/dev_fy_config_new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun5",
ProxyList: []*rpc.Proxy{},
CloneList: []*rpc.Clone{},
},
},
}
output, err := genOutput(status, FormatTable)
if err != nil {
t.Fatal(err)
}
fmt.Println(output)
}
func TestPrint(t *testing.T) {
var status = &rpc.StatusResponse{
List: []*rpc.Status{
{
ID: 0,
ClusterID: "ac6d8dfb-1d23-4f2a-b11e-9c775fd22b84",
Cluster: "ccm6epn7qvcplhs3o8p00",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/test-feiyan-config-private-new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun4",
ProxyList: []*rpc.Proxy{},
CloneList: []*rpc.Clone{},
},
{
ID: 1,
ClusterID: "c08cae70-0021-46c9-a1dc-38e6a2f11443",
Cluster: "ccnepblsebp68ivej4a20",
Mode: "full",
Kubeconfig: "/Users/bytedance/.kube/dev_fy_config_new",
Namespace: "vke-system",
Status: "Connected",
Netif: "utun5",
ProxyList: []*rpc.Proxy{},
CloneList: []*rpc.Clone{},
},
},
}
output, err := genOutput(status, FormatTable)
if err != nil {
t.Fatal(err)
}
fmt.Println(output)
}

View File

@@ -0,0 +1,30 @@
package cmds
import (
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/syncthing"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdSyncthing(cmdutil.Factory) *cobra.Command {
var detach bool
var dir string
cmd := &cobra.Command{
Use: "syncthing",
Short: i18n.T("Syncthing"),
Long: templates.LongDesc(i18n.T(`Syncthing`)),
RunE: func(cmd *cobra.Command, args []string) (err error) {
go util.StartupPProfForServer(0)
return syncthing.StartServer(cmd.Context(), detach, dir)
},
Hidden: true,
DisableFlagsInUseLine: true,
}
cmd.Flags().StringVar(&dir, "dir", "", "dir")
cmd.Flags().BoolVarP(&detach, "detach", "d", false, "Run syncthing in background")
return cmd
}

View File

@@ -0,0 +1,98 @@
package cmds
import (
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/utils/ptr"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
pkgssh "github.com/wencaiwulue/kubevpn/v2/pkg/ssh"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func CmdUninstall(f cmdutil.Factory) *cobra.Command {
var sshConf = &pkgssh.SshConfig{}
cmd := &cobra.Command{
Use: "uninstall",
Short: "Uninstall all resource create by kubevpn in k8s cluster",
Long: templates.LongDesc(i18n.T(`
Uninstall all resource create by kubevpn in k8s cluster
Uninstall will delete all resources create by kubevpn in k8s cluster, like deployment, service, serviceAccount...
and it will also delete local develop docker containers, docker networks. delete hosts entry added by kubevpn,
cleanup DNS settings.
`)),
Example: templates.Examples(i18n.T(`
# Uninstall default namespace
kubevpn uninstall
# Uninstall another namespace test
kubevpn uninstall -n test
# Uninstall cluster api-server behind of bastion host or ssh jump host
kubevpn uninstall --ssh-addr 192.168.1.100:22 --ssh-username root --ssh-keyfile ~/.ssh/ssh.pem
# It also supports ProxyJump, like
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────────┐
│ pc ├────►│ ssh1 ├────►│ ssh2 ├────►│ ssh3 ├─────►... ─────► │ api-server │
└──────┘ └──────┘ └──────┘ └──────┘ └────────────┘
kubevpn uninstall --ssh-alias <alias>
# Support ssh auth GSSAPI
kubevpn uninstall --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-keytab /path/to/keytab
kubevpn uninstall --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-cache /path/to/cache
kubevpn uninstall --ssh-addr <HOST:PORT> --ssh-username <USERNAME> --gssapi-password <PASSWORD>
`)),
PreRunE: func(cmd *cobra.Command, args []string) error {
plog.InitLoggerForClient()
return daemon.StartupDaemon(cmd.Context())
},
RunE: func(cmd *cobra.Command, args []string) error {
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return err
}
cli, err := daemon.GetClient(false)
if err != nil {
return err
}
disconnectResp, err := cli.Disconnect(cmd.Context(), &rpc.DisconnectRequest{
KubeconfigBytes: ptr.To(string(bytes)),
Namespace: ptr.To(ns),
SshJump: sshConf.ToRPC(),
})
if err != nil {
plog.G(cmd.Context()).Warnf("Failed to disconnect from cluter: %v", err)
} else {
_ = util.PrintGRPCStream[rpc.DisconnectResponse](disconnectResp)
}
req := &rpc.UninstallRequest{
KubeconfigBytes: string(bytes),
Namespace: ns,
SshJump: sshConf.ToRPC(),
}
resp, err := cli.Uninstall(cmd.Context(), req)
if err != nil {
return err
}
err = util.PrintGRPCStream[rpc.UninstallResponse](resp)
if err != nil {
if status.Code(err) == codes.Canceled {
return nil
}
return err
}
return nil
},
}
pkgssh.AddSshFlags(cmd.Flags(), sshConf)
return cmd
}

View File

@@ -0,0 +1,59 @@
package cmds
import (
"fmt"
"net/http"
"os"
"github.com/spf13/cobra"
"golang.org/x/oauth2"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/upgrade"
)
func CmdUpgrade(cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "upgrade",
Short: i18n.T("Upgrade kubevpn client to latest version"),
Long: templates.LongDesc(i18n.T(`
Upgrade kubevpn client to latest version, automatically download and install latest kubevpn from GitHub.
disconnect all from k8s cluster, leave all resources, remove all clone resource, and then,
upgrade local daemon grpc server to latest version.
`)),
RunE: func(cmd *cobra.Command, args []string) error {
const (
envLatestUrl = "KUBEVPN_LATEST_VERSION_URL"
)
plog.InitLoggerForClient()
var client = http.DefaultClient
if config.GitHubOAuthToken != "" {
client = oauth2.NewClient(cmd.Context(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: config.GitHubOAuthToken, TokenType: "Bearer"}))
}
var url = os.Getenv(envLatestUrl)
if url == "" {
var latestVersion string
var needsUpgrade bool
var err error
url, latestVersion, needsUpgrade, err = upgrade.NeedsUpgrade(cmd.Context(), client, config.Version)
if err != nil {
return err
}
if !needsUpgrade {
_, _ = fmt.Fprintln(os.Stdout, fmt.Sprintf("Already up to date, don't needs to upgrade, version: %s", latestVersion))
return nil
}
_, _ = fmt.Fprintln(os.Stdout, fmt.Sprintf("Current version is: %s less than latest version: %s, needs to upgrade", config.Version, latestVersion))
_ = os.Setenv(envLatestUrl, url)
_ = quit(cmd.Context(), true)
_ = quit(cmd.Context(), false)
}
return upgrade.Main(cmd.Context(), client, url)
},
}
return cmd
}

View File

@@ -0,0 +1,76 @@
package cmds
import (
"context"
"fmt"
"runtime"
"runtime/debug"
"time"
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
)
// --ldflags -X
var (
OsArch = ""
BuildTime = ""
Branch = ""
)
func reformatDate(buildTime string) string {
t, errTime := time.Parse(time.RFC3339Nano, buildTime)
if errTime == nil {
return t.Format("2006-01-02 15:04:05")
}
return buildTime
}
func CmdVersion(cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: i18n.T("Print the client version information"),
Long: templates.LongDesc(i18n.T(`
Print the client version information
`)),
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("KubeVPN: CLI\n")
fmt.Printf(" Version: %s\n", config.Version)
fmt.Printf(" Daemon: %s\n", getDaemonVersion())
fmt.Printf(" Image: %s\n", config.Image)
fmt.Printf(" Branch: %s\n", Branch)
fmt.Printf(" Git commit: %s\n", config.GitCommit)
fmt.Printf(" Built time: %s\n", reformatDate(BuildTime))
fmt.Printf(" Built OS/Arch: %s\n", OsArch)
fmt.Printf(" Built Go version: %s\n", runtime.Version())
},
}
return cmd
}
func init() {
// Prefer version number inserted at build using --ldflags
if config.Version == "" {
if i, ok := debug.ReadBuildInfo(); ok {
config.Version = i.Main.Version
}
}
}
func getDaemonVersion() string {
cli, err := daemon.GetClient(false)
if err != nil {
return "unknown"
}
version, err := cli.Version(context.Background(), &rpc.VersionRequest{})
if err != nil {
return "unknown"
}
return version.Version
}

View File

@@ -0,0 +1,32 @@
package cmds
import (
"github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
"github.com/wencaiwulue/kubevpn/v2/pkg/webhook"
)
func CmdWebhook(f cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "webhook",
Hidden: true,
Short: i18n.T("Starts a HTTP server, useful for creating MutatingAdmissionWebhook"),
Long: templates.LongDesc(i18n.T(`
Starts a HTTP server, useful for creating MutatingAdmissionWebhook.
After deploying it to Kubernetes cluster, the Administrator needs to create a MutatingWebhookConfiguration
in the Kubernetes cluster to register remote webhook admission controllers.
`)),
Args: cobra.MaximumNArgs(0),
PreRun: func(cmd *cobra.Command, args []string) {
go util.StartupPProfForServer(0)
},
RunE: func(cmd *cobra.Command, args []string) error {
return webhook.Main(f)
},
}
return cmd
}

View File

@@ -1,20 +1,15 @@
package main
import (
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/cmd/kubevpn/cmds"
"github.com/wencaiwulue/kubevpn/util"
"net/http"
ctrl "sigs.k8s.io/controller-runtime"
_ "k8s.io/client-go/plugin/pkg/client/auth"
_ "net/http/pprof"
"github.com/wencaiwulue/kubevpn/v2/cmd/kubevpn/cmds"
)
func main() {
if !util.IsAdmin() {
util.RunWithElevated()
} else {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
_ = cmds.RootCmd.Execute()
}
ctx := ctrl.SetupSignalHandler()
_ = cmds.NewKubeVPNCommand().ExecuteContext(ctx)
}

View File

@@ -1,87 +0,0 @@
package core
import (
"context"
"errors"
"fmt"
"math"
"net"
)
var (
// ErrorEmptyChain is an error that implies the chain is empty.
ErrorEmptyChain = errors.New("empty chain")
)
// Chain is a proxy chain that holds a list of proxy node groups.
type Chain struct {
Retries int
node *Node
}
// NewChain creates a proxy chain with a list of proxy nodes.
// It creates the node groups automatically, one group per node.
func NewChain(retry int, node *Node) *Chain {
return &Chain{Retries: retry, node: node}
}
func (c *Chain) Node() *Node {
return c.node
}
// IsEmpty checks if the chain is empty.
// An empty chain means that there is no proxy node or node group in the chain.
func (c *Chain) IsEmpty() bool {
return c == nil || c.node == nil
}
// DialContext connects to the address on the named network using the provided context.
func (c *Chain) DialContext(ctx context.Context, network, address string) (conn net.Conn, err error) {
for i := 0; i < int(math.Max(float64(1), float64(c.Retries))); i++ {
conn, err = c.dial(ctx, network, address)
if err == nil {
break
}
}
return
}
func (c *Chain) dial(ctx context.Context, network, address string) (net.Conn, error) {
ipAddr := address
if address != "" {
ipAddr = c.resolve(address)
}
if c.IsEmpty() {
return nil, ErrorEmptyChain
}
conn, err := c.getConn(ctx)
if err != nil {
return nil, err
}
cc, err := c.Node().Client.ConnectContext(ctx, conn, network, ipAddr)
if err != nil {
_ = conn.Close()
return nil, err
}
return cc, nil
}
func (*Chain) resolve(addr string) string {
if host, port, err := net.SplitHostPort(addr); err == nil {
if ips, err := net.LookupIP(host); err == nil && len(ips) > 0 {
return fmt.Sprintf("%s:%s", ips[0].String(), port)
}
}
return addr
}
// getConn obtains a connection to the last node of the chain.
func (c *Chain) getConn(_ context.Context) (net.Conn, error) {
if c.IsEmpty() {
return nil, ErrorEmptyChain
}
return c.Node().Client.Dial(c.Node().Addr)
}

View File

@@ -1,25 +0,0 @@
package core
import (
"context"
"net"
)
// Client is a proxy client.
// A client is divided into two layers: connector and transporter.
// Connector is responsible for connecting to the destination address through this proxy.
// Transporter performs a handshake with this proxy.
type Client struct {
Connector
Transporter
}
// Connector is responsible for connecting to the destination address.
type Connector interface {
ConnectContext(ctx context.Context, conn net.Conn, network, address string) (net.Conn, error)
}
// Transporter is responsible for handshaking with the proxy server.
type Transporter interface {
Dial(addr string) (net.Conn, error)
}

View File

@@ -1,44 +0,0 @@
package core
import (
"context"
"github.com/wencaiwulue/kubevpn/tun"
"net"
)
// Handler is a proxy server handler
type Handler interface {
Init(options ...HandlerOption)
Handle(ctx context.Context, conn net.Conn)
}
// HandlerOptions describes the options for Handler.
type HandlerOptions struct {
Chain *Chain
Node *Node
IPRoutes []tun.IPRoute
}
// HandlerOption allows a common way to set handler options.
type HandlerOption func(opts *HandlerOptions)
// ChainHandlerOption sets the Chain option of HandlerOptions.
func ChainHandlerOption(chain *Chain) HandlerOption {
return func(opts *HandlerOptions) {
opts.Chain = chain
}
}
// NodeHandlerOption set the server node for server handler.
func NodeHandlerOption(node *Node) HandlerOption {
return func(opts *HandlerOptions) {
opts.Node = node
}
}
// IPRoutesHandlerOption sets the IP routes for tun tunnel.
func IPRoutesHandlerOption(routes ...tun.IPRoute) HandlerOption {
return func(opts *HandlerOptions) {
opts.IPRoutes = routes
}
}

View File

@@ -1,67 +0,0 @@
package core
import (
"errors"
"net/url"
"strconv"
"strings"
)
var (
ErrorInvalidNode = errors.New("invalid node")
)
// Node is a proxy node, mainly used to construct a proxy chain.
type Node struct {
Addr string
Protocol string
Transport string
Remote string // remote address, used by tcp/udp port forwarding
Values url.Values
Client *Client
}
// ParseNode parses the node info.
// The proxy node string pattern is [scheme://][user:pass@host]:port.
func ParseNode(s string) (node *Node, err error) {
s = strings.TrimSpace(s)
if s == "" {
return nil, ErrorInvalidNode
}
u, err := url.Parse(s)
if err != nil {
return
}
node = &Node{
Addr: u.Host,
Remote: strings.Trim(u.EscapedPath(), "/"),
Values: u.Query(),
}
u.RawQuery = ""
u.User = nil
switch u.Scheme {
case "tun":
node.Protocol = u.Scheme
node.Transport = u.Scheme
case "tcp":
node.Protocol = "tcp"
node.Transport = "tcp"
default:
return nil, ErrorInvalidNode
}
return
}
// Get returns node parameter specified by key.
func (node *Node) Get(key string) string {
return node.Values.Get(key)
}
// GetInt converts node parameter value to int.
func (node *Node) GetInt(key string) int {
n, _ := strconv.Atoi(node.Get(key))
return n
}

View File

@@ -1,72 +0,0 @@
package core
import (
"context"
"k8s.io/client-go/util/retry"
"net"
"time"
log "github.com/sirupsen/logrus"
)
// Server is a proxy server.
type Server struct {
Listener net.Listener
Handler Handler
}
// Addr returns the address of the server
func (s *Server) Addr() net.Addr {
return s.Listener.Addr()
}
// Close closes the server
func (s *Server) Close() error {
return s.Listener.Close()
}
// Serve serves as a proxy server.
func (s *Server) Serve(ctx context.Context, h Handler) error {
if h == nil {
h = s.Handler
}
l := s.Listener
var tempDelay time.Duration
go func() {
select {
case <-ctx.Done():
err := retry.OnError(retry.DefaultBackoff, func(err error) bool {
return err != nil
}, func() error {
return l.Close()
})
if err != nil {
log.Warnf("error while close listener, err: %v", err)
}
}
}()
for ctx.Err() == nil {
conn, e := l.Accept()
if e != nil {
if ne, ok := e.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
log.Warnf("server: Accept error: %v; retrying in %v", e, tempDelay)
time.Sleep(tempDelay)
continue
}
return e
}
tempDelay = 0
go h.Handle(ctx, conn)
}
return nil
}

View File

@@ -1,52 +0,0 @@
package core
import (
"crypto/tls"
"github.com/wencaiwulue/kubevpn/tlsconfig"
"github.com/wencaiwulue/kubevpn/util"
"net"
)
// tcpTransporter is a raw TCP transporter.
type tcpTransporter struct{}
// TCPTransporter creates a raw TCP client.
func TCPTransporter() Transporter {
return &tcpTransporter{}
}
func (tr *tcpTransporter) Dial(addr string) (net.Conn, error) {
dialer := &net.Dialer{Timeout: util.DialTimeout}
return tls.DialWithDialer(dialer, "tcp", addr, tlsconfig.TlsconfigClient)
}
type tcpListener struct {
net.Listener
}
// TCPListener creates a Listener for TCP proxy server.
func TCPListener(addr string) (net.Listener, error) {
laddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
ln, err := net.ListenTCP("tcp", laddr)
if err != nil {
return nil, err
}
return &tcpListener{Listener: tcpKeepAliveListener{TCPListener: ln}}, nil
}
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
_ = tc.SetKeepAlive(true)
_ = tc.SetKeepAlivePeriod(util.KeepAliveTime)
return tc, nil
}

View File

@@ -1,255 +0,0 @@
package core
import (
"bytes"
"context"
"fmt"
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/util"
"net"
"time"
)
type fakeUDPTunConnector struct {
}
// UDPOverTCPTunnelConnector creates a connector for UDP-over-TCP
func UDPOverTCPTunnelConnector() Connector {
return &fakeUDPTunConnector{}
}
func (c *fakeUDPTunConnector) ConnectContext(_ context.Context, conn net.Conn, network, address string) (net.Conn, error) {
switch network {
case "tcp", "tcp4", "tcp6":
return nil, fmt.Errorf("%s unsupported", network)
}
_ = conn.SetDeadline(time.Now().Add(util.ConnectTimeout))
defer conn.SetDeadline(time.Time{})
targetAddr, _ := net.ResolveUDPAddr("udp", address)
return newFakeUDPTunnelConnOverTCP(conn, targetAddr)
}
type fakeUdpHandler struct {
}
// TCPHandler creates a server Handler
func TCPHandler() Handler {
return &fakeUdpHandler{}
}
func (h *fakeUdpHandler) Init(...HandlerOption) {
}
func (h *fakeUdpHandler) Handle(ctx context.Context, conn net.Conn) {
defer conn.Close()
if util.Debug {
log.Debugf("[tcpserver] %s -> %s\n", conn.RemoteAddr(), conn.LocalAddr())
}
h.handleUDPTunnel(conn)
}
func (h *fakeUdpHandler) transportUDP(relay, peer net.PacketConn) (err error) {
errChan := make(chan error, 2)
var clientAddr net.Addr
go func() {
b := util.MPool.Get().([]byte)
defer util.MPool.Put(b)
for {
n, laddr, err := relay.ReadFrom(b)
if err != nil {
errChan <- err
return
}
if clientAddr == nil {
clientAddr = laddr
}
dgram, err := ReadDatagramPacket(bytes.NewReader(b[:n]))
if err != nil {
log.Errorln(err)
errChan <- err
return
}
raddr, err := net.ResolveUDPAddr("udp", dgram.Addr())
if err != nil {
log.Debugf("[tcpserver-udp] addr error, addr: %s, err: %v", dgram.Addr(), err)
continue // drop silently
}
if _, err := peer.WriteTo(dgram.Data, raddr); err != nil {
errChan <- err
return
}
if util.Debug {
log.Debugf("[tcpserver-udp] %s >>> %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
}
}
}()
go func() {
b := util.MPool.Get().([]byte)
defer util.MPool.Put(b)
for {
n, raddr, err := peer.ReadFrom(b)
if err != nil {
errChan <- err
return
}
if clientAddr == nil {
continue
}
buf := bytes.Buffer{}
dgram := NewDatagramPacket(raddr, b[:n])
_ = dgram.Write(&buf)
if _, err := relay.WriteTo(buf.Bytes(), clientAddr); err != nil {
errChan <- err
return
}
if util.Debug {
log.Debugf("[tcpserver-udp] %s <<< %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
}
}
}()
return <-errChan
}
func (h *fakeUdpHandler) handleUDPTunnel(conn net.Conn) {
// serve tunnel udp, tunnel <-> remote, handle tunnel udp request
bindAddr, _ := net.ResolveUDPAddr("udp", ":0")
uc, err := net.ListenUDP("udp", bindAddr)
if err != nil {
log.Debugf("[tcpserver] udp-tun %s -> %s : %s", conn.RemoteAddr(), bindAddr, err)
return
}
defer uc.Close()
if util.Debug {
log.Debugf("[tcpserver] udp-tun %s <- %s\n", conn.RemoteAddr(), uc.LocalAddr())
}
log.Debugf("[tcpserver] udp-tun %s <-> %s", conn.RemoteAddr(), uc.LocalAddr())
_ = h.tunnelServerUDP(conn, uc)
log.Debugf("[tcpserver] udp-tun %s >-< %s", conn.RemoteAddr(), uc.LocalAddr())
return
}
func (h *fakeUdpHandler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err error) {
errChan := make(chan error, 2)
go func() {
b := util.MPool.Get().([]byte)
defer util.MPool.Put(b)
for {
n, addr, err := pc.ReadFrom(b)
if err != nil {
log.Debugf("[udp-tun] %s : %s", cc.RemoteAddr(), err)
errChan <- err
return
}
// pipe from peer to tunnel
dgram := NewDatagramPacket(addr, b[:n])
if err := dgram.Write(cc); err != nil {
log.Debugf("[tcpserver] udp-tun %s <- %s : %s", cc.RemoteAddr(), dgram.Addr(), err)
errChan <- err
return
}
if util.Debug {
log.Debugf("[tcpserver] udp-tun %s <<< %s length: %d", cc.RemoteAddr(), dgram.Addr(), len(dgram.Data))
}
}
}()
go func() {
for {
dgram, err := ReadDatagramPacket(cc)
if err != nil {
log.Debugf("[udp-tun] %s -> 0 : %v", cc.RemoteAddr(), err)
errChan <- err
return
}
// pipe from tunnel to peer
addr, err := net.ResolveUDPAddr("udp", dgram.Addr())
if err != nil {
log.Debugf("[tcpserver-udp] addr error, addr: %s, err: %v", dgram.Addr(), err)
continue // drop silently
}
if _, err := pc.WriteTo(dgram.Data, addr); err != nil {
log.Debugf("[tcpserver] udp-tun %s -> %s : %s", cc.RemoteAddr(), addr, err)
errChan <- err
return
}
if util.Debug {
log.Debugf("[tcpserver] udp-tun %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data))
}
}
}()
return <-errChan
}
// fake udp connect over tcp
type fakeUDPTunnelConn struct {
// tcp connection
net.Conn
targetAddr net.Addr
}
func newFakeUDPTunnelConnOverTCP(conn net.Conn, targetAddr net.Addr) (net.Conn, error) {
return &fakeUDPTunnelConn{
Conn: conn,
targetAddr: targetAddr,
}, nil
}
func (c *fakeUDPTunnelConn) Read(b []byte) (n int, err error) {
n, _, err = c.ReadFrom(b)
return
}
func (c *fakeUDPTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
dgram, err := ReadDatagramPacket(c.Conn)
if err != nil {
log.Debug(err)
return
}
n = copy(b, dgram.Data)
addr, err = net.ResolveUDPAddr("udp", dgram.Addr())
if err != nil {
log.Debugf("[tcpserver-udp] addr error, addr: %s, err: %v", dgram.Addr(), err)
}
return
}
func (c *fakeUDPTunnelConn) Write(b []byte) (n int, err error) {
return c.WriteTo(b, c.targetAddr)
}
func (c *fakeUDPTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
dgram := NewDatagramPacket(addr, b)
if err = dgram.Write(c.Conn); err != nil {
return
}
return len(b), nil
}
func (c *fakeUDPTunnelConn) Close() error {
return c.Conn.Close()
}
func (c *fakeUDPTunnelConn) CloseWrite() error {
if cc, ok := c.Conn.(interface{ CloseWrite() error }); ok {
return cc.CloseWrite()
}
return nil
}
func (c *fakeUDPTunnelConn) CloseRead() error {
if cc, ok := c.Conn.(interface{ CloseRead() error }); ok {
return cc.CloseRead()
}
return nil
}

View File

@@ -1,296 +0,0 @@
package core
import (
"context"
"errors"
"fmt"
"github.com/wencaiwulue/kubevpn/util"
"net"
"sync"
"time"
"github.com/shadowsocks/go-shadowsocks2/shadowaead"
log "github.com/sirupsen/logrus"
"github.com/songgao/water/waterutil"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
func ipToTunRouteKey(ip net.IP) string {
return ip.To16().String()
}
type tunHandler struct {
options *HandlerOptions
routes sync.Map
chExit chan struct{}
}
// TunHandler creates a handler for tun tunnel.
func TunHandler(opts ...HandlerOption) Handler {
h := &tunHandler{
options: &HandlerOptions{},
chExit: make(chan struct{}, 1),
}
for _, opt := range opts {
opt(h.options)
}
return h
}
func (h *tunHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
}
func (h *tunHandler) Handle(ctx context.Context, conn net.Conn) {
defer conn.Close()
var err error
var raddr net.Addr
if addr := h.options.Node.Remote; addr != "" {
raddr, err = net.ResolveUDPAddr("udp", addr)
if err != nil {
log.Debugf("[tun] %s: remote addr: %v", conn.LocalAddr(), err)
return
}
}
var tempDelay time.Duration
for ctx.Err() == nil {
err = func() error {
var err error
var pc net.PacketConn
if raddr != nil && !h.options.Chain.IsEmpty() {
cc, err := h.options.Chain.DialContext(ctx, "udp", raddr.String())
if err != nil {
return err
}
var ok bool
pc, ok = cc.(net.PacketConn)
if !ok {
err = errors.New("not a packet connection")
log.Debugf("[tun] %s - %s: %s", conn.LocalAddr(), raddr, err)
return err
}
} else {
laddr, _ := net.ResolveUDPAddr("udp", h.options.Node.Addr)
pc, err = net.ListenUDP("udp", laddr)
}
if err != nil {
return err
}
return h.transportTun(ctx, conn, pc, raddr)
}()
if err != nil {
log.Debugf("[tun] %s: %v", conn.LocalAddr(), err)
}
select {
case <-h.chExit:
return
case <-ctx.Done():
h.chExit <- struct{}{}
default:
fmt.Println("next loop")
}
if err != nil {
if tempDelay == 0 {
tempDelay = 1000 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 6 * time.Second; tempDelay > max {
tempDelay = max
}
time.Sleep(tempDelay)
continue
}
tempDelay = 0
}
}
func (h *tunHandler) findRouteFor(dst net.IP) net.Addr {
if v, ok := h.routes.Load(ipToTunRouteKey(dst)); ok {
return v.(net.Addr)
}
for _, route := range h.options.IPRoutes {
if route.Dest.Contains(dst) && route.Gateway != nil {
if v, ok := h.routes.Load(ipToTunRouteKey(route.Gateway)); ok {
return v.(net.Addr)
}
}
}
return nil
}
func (h *tunHandler) transportTun(ctx context.Context, tun net.Conn, conn net.PacketConn, raddr net.Addr) error {
errChan := make(chan error, 2)
defer func() {
if c, ok := conn.(interface{ CloseRead() error }); ok {
_ = c.CloseRead()
}
if c, ok := conn.(interface{ CloseWrite() error }); ok {
_ = c.CloseWrite()
}
_ = conn.Close()
}()
go func() {
for ctx.Err() == nil {
err := func() error {
b := util.SPool.Get().([]byte)
defer util.SPool.Put(b)
n, err := tun.Read(b)
if err != nil {
select {
case h.chExit <- struct{}{}:
default:
}
return err
}
var src, dst net.IP
if waterutil.IsIPv4(b[:n]) {
header, err := ipv4.ParseHeader(b[:n])
if err != nil {
log.Debugf("[tun] %s: %v", tun.LocalAddr(), err)
return nil
}
if util.Debug {
log.Debugf("[tun] %s", header.String())
}
src, dst = header.Src, header.Dst
} else if waterutil.IsIPv6(b[:n]) {
header, err := ipv6.ParseHeader(b[:n])
if err != nil {
log.Debugf("[tun] %s: %v", tun.LocalAddr(), err)
return nil
}
if util.Debug {
log.Debugf("[tun] %s", header.String())
}
src, dst = header.Src, header.Dst
} else {
log.Debugf("[tun] unknown packet")
return nil
}
// client side, deliver packet directly.
if raddr != nil {
_, err := conn.WriteTo(b[:n], raddr)
return err
}
addr := h.findRouteFor(dst)
if addr == nil {
log.Debugf("[tun] no route for %s -> %s", src, dst)
return nil
}
if util.Debug {
log.Debugf("[tun] find route: %s -> %s", dst, addr)
}
if _, err := conn.WriteTo(b[:n], addr); err != nil {
return err
}
return nil
}()
if err != nil {
errChan <- err
return
}
}
}()
go func() {
for ctx.Err() == nil {
err := func() error {
b := util.SPool.Get().([]byte)
defer util.SPool.Put(b)
n, addr, err := conn.ReadFrom(b)
if err != nil && err != shadowaead.ErrShortPacket {
return err
}
var src, dst net.IP
if waterutil.IsIPv4(b[:n]) {
header, err := ipv4.ParseHeader(b[:n])
if err != nil {
log.Debugf("[tun] %s: %v", tun.LocalAddr(), err)
return nil
}
if util.Debug {
log.Debugf("[tun] %s", header.String())
}
src, dst = header.Src, header.Dst
} else if waterutil.IsIPv6(b[:n]) {
header, err := ipv6.ParseHeader(b[:n])
if err != nil {
log.Debugf("[tun] %s: %v", tun.LocalAddr(), err)
return nil
}
if util.Debug {
log.Debugf("[tun] %s", header.String())
}
src, dst = header.Src, header.Dst
} else {
log.Debugf("[tun] unknown packet")
return nil
}
// client side, deliver packet to tun device.
if raddr != nil {
_, err := tun.Write(b[:n])
return err
}
routeKey := ipToTunRouteKey(src)
if actual, loaded := h.routes.LoadOrStore(routeKey, addr); loaded {
if actual.(net.Addr).String() != addr.String() {
log.Debugf("[tun] update route: %s -> %s (old %s)", src, addr, actual.(net.Addr))
h.routes.Store(routeKey, addr)
}
} else {
log.Debugf("[tun] new route: %s -> %s", src, addr)
}
if addr := h.findRouteFor(dst); addr != nil {
if util.Debug {
log.Debugf("[tun] find route: %s -> %s", dst, addr)
}
_, err := conn.WriteTo(b[:n], addr)
return err
}
if _, err := tun.Write(b[:n]); err != nil {
select {
case h.chExit <- struct{}{}:
default:
}
return err
}
return nil
}()
if err != nil {
errChan <- err
return
}
}
}()
select {
case err := <-errChan:
return err
case <-ctx.Done():
return nil
}
}

View File

@@ -1,146 +0,0 @@
package core
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"github.com/wencaiwulue/kubevpn/util"
"io"
"net"
"strconv"
"strings"
)
const (
AddrIPv4 uint8 = 1
AddrIPv6 = 2
AddrDomain = 3
)
type DatagramPacket struct {
Type uint8 // [1]byte
Host string // [?]byte, first byte is length if it's a domain
Port uint16 // [2]byte
DataLength uint16 // [2]byte
Data []byte // []byte
}
func (addr *DatagramPacket) String() string {
if addr == nil {
return ""
}
return fmt.Sprintf("Type: %d, Host: %s, Port: %d, DataLength: %d, Data: %v\n",
addr.Type, addr.Host, addr.Port, addr.DataLength, addr.Data)
}
func NewDatagramPacket(addr net.Addr, data []byte) (r *DatagramPacket) {
s := addr.String()
var t uint8
if strings.Count(s, ":") >= 2 {
t = AddrIPv6
} else {
if ip := net.ParseIP(strings.Split(s, ":")[0]); ip != nil {
t = AddrIPv4
} else {
t = AddrDomain
}
}
host, port, _ := net.SplitHostPort(s)
atoi, _ := strconv.Atoi(port)
// todo if host is a domain
r = &DatagramPacket{
Host: host,
Port: uint16(atoi),
Type: t,
DataLength: uint16(len(data)),
Data: data,
}
return r
}
func (addr *DatagramPacket) Addr() string {
return net.JoinHostPort(addr.Host, strconv.Itoa(int(addr.Port)))
}
func ReadDatagramPacket(r io.Reader) (rr *DatagramPacket, errsss error) {
b := util.LPool.Get().([]byte)
defer util.LPool.Put(b)
_, err := io.ReadFull(r, b[:1])
if err != nil {
return nil, err
}
atype := b[0]
d := &DatagramPacket{Type: atype}
hostLength := 0
switch atype {
case AddrIPv4:
hostLength = net.IPv4len
case AddrIPv6:
hostLength = net.IPv6len
case AddrDomain:
_, err = io.ReadFull(r, b[:1])
if err != nil {
return nil, err
}
hostLength = int(b[0])
default:
return nil, errors.New("")
}
if _, err = io.ReadFull(r, b[:hostLength]); err != nil {
return nil, err
}
var host string
switch atype {
case AddrIPv4:
host = net.IPv4(b[0], b[1], b[2], b[3]).String()
case AddrIPv6:
p := make(net.IP, net.IPv6len)
copy(p, b[:hostLength])
host = p.String()
case AddrDomain:
host = string(b[:hostLength])
}
d.Host = host
if _, err = io.ReadFull(r, b[:4]); err != nil {
return nil, err
}
d.Port = binary.BigEndian.Uint16(b[:2])
d.DataLength = binary.BigEndian.Uint16(b[2:4])
if _, err = io.ReadFull(r, b[:d.DataLength]); err != nil && (err != io.ErrUnexpectedEOF || err != io.EOF) {
return nil, err
}
i := make([]byte, d.DataLength)
copy(i, b[:d.DataLength])
d.Data = i
rr = d
return d, nil
}
func (addr *DatagramPacket) Write(w io.Writer) error {
buf := bytes.Buffer{}
buf.WriteByte(addr.Type)
switch addr.Type {
case AddrIPv4:
buf.Write(net.ParseIP(addr.Host).To4())
case AddrIPv6:
buf.Write(net.ParseIP(addr.Host).To16())
case AddrDomain:
buf.WriteByte(byte(len(addr.Host)))
buf.WriteString(addr.Host)
}
i := make([]byte, 2)
binary.BigEndian.PutUint16(i, addr.Port)
buf.Write(i)
binary.BigEndian.PutUint16(i, uint16(len(addr.Data)))
buf.Write(i)
if _, err := buf.Write(addr.Data); err != nil {
return err
}
_, err := buf.WriteTo(w)
return err
}

View File

@@ -1,55 +0,0 @@
package dns
import (
"bytes"
"context"
miekgdns "github.com/miekg/dns"
"github.com/pkg/errors"
"github.com/wencaiwulue/kubevpn/util"
v12 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
func GetDNSServiceIPFromPod(clientset *kubernetes.Clientset, restclient *rest.RESTClient, config *rest.Config, podName, namespace string) (*miekgdns.ClientConfig, error) {
var ipp []string
if ips, err := getDNSIPFromDnsPod(clientset); err == nil {
ipp = ips
}
resolvConfStr, err := util.Shell(clientset, restclient, config, podName, namespace, "cat /etc/resolv.conf")
if err != nil {
return nil, err
}
resolvConf, err := miekgdns.ClientConfigFromReader(bytes.NewBufferString(resolvConfStr))
if err != nil {
return nil, err
}
if len(ipp) != 0 {
resolvConf.Servers = append(resolvConf.Servers, make([]string, len(ipp))...)
copy(resolvConf.Servers[len(ipp):], resolvConf.Servers[:len(resolvConf.Servers)-len(ipp)])
for i := range ipp {
resolvConf.Servers[i] = ipp[i]
}
}
return resolvConf, nil
}
func getDNSIPFromDnsPod(clientset *kubernetes.Clientset) (ips []string, err error) {
serviceList, err := clientset.CoreV1().Pods(v1.NamespaceSystem).List(context.Background(), v1.ListOptions{
LabelSelector: fields.OneTermEqualSelector("k8s-app", "kube-dns").String(),
})
if err != nil {
return
}
for _, pod := range serviceList.Items {
if pod.Status.Phase == v12.PodRunning && pod.DeletionTimestamp == nil {
ips = append(ips, pod.Status.PodIP)
}
}
if len(ips) == 0 {
return nil, errors.New("")
}
return ips, nil
}

View File

@@ -1,37 +0,0 @@
//go:build linux
// +build linux
package dns
import (
miekgdns "github.com/miekg/dns"
log "github.com/sirupsen/logrus"
"os"
"os/exec"
)
// systemd-resolve --status, systemd-resolve --flush-caches
func SetupDNS(config *miekgdns.ClientConfig) error {
tunName := os.Getenv("tunName")
if len(tunName) == 0 {
tunName = "tun0"
}
cmd := exec.Command("systemd-resolve", []string{
"--set-dns",
config.Servers[0],
"--interface",
tunName,
"--set-domain=" + config.Search[0],
"--set-domain=" + config.Search[1],
"--set-domain=" + config.Search[2],
}...)
output, err := cmd.CombinedOutput()
if err != nil {
log.Warnf("cmd: %s, output: %s, error: %v\n", cmd.Args, string(output), err)
}
return nil
}
func CancelDNS() {
}

View File

@@ -1,257 +0,0 @@
//go:build darwin
// +build darwin
package dns
import (
"context"
"fmt"
"github.com/fsnotify/fsnotify"
miekgdns "github.com/miekg/dns"
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/util"
"io/fs"
"io/ioutil"
"k8s.io/apimachinery/pkg/util/sets"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
)
var cancel context.CancelFunc
var resolv = "/etc/resolv.conf"
// SetupDNS support like
// service:port
// service.namespace:port
// service.namespace.svc:port
// service.namespace.svc.cluster:port
// service.namespace.svc.cluster.local:port
func SetupDNS(config *miekgdns.ClientConfig) error {
usingResolver(config)
_ = exec.Command("killall", "mDNSResponderHelper").Run()
_ = exec.Command("killall", "-HUP", "mDNSResponder").Run()
_ = exec.Command("dscacheutil", "-flushcache").Run()
return nil
}
func usingResolver(clientConfig *miekgdns.ClientConfig) {
var err error
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
if err = os.MkdirAll(filepath.Join("/", "etc", "resolver"), fs.ModePerm); err != nil {
log.Error(err)
}
config := miekgdns.ClientConfig{
Servers: clientConfig.Servers,
Search: clientConfig.Search,
Ndots: 5,
Timeout: 1,
}
// for support like: service:port, service.namespace.svc.cluster.local:port
filename := filepath.Join("/", "etc", "resolver", "local")
_ = ioutil.WriteFile(filename, []byte(toString(config)), 0644)
// for support like: service.namespace:port, service.namespace.svc:port, service.namespace.svc.cluster:port
port := util.GetAvailableUDPPortOrDie()
go func(port int, clientConfig *miekgdns.ClientConfig) {
if err = NewDNSServer("udp", "127.0.0.1:"+strconv.Itoa(port), clientConfig); err != nil {
log.Warnln(err)
}
}(port, clientConfig)
config = miekgdns.ClientConfig{
Servers: []string{"127.0.0.1"},
Search: clientConfig.Search,
Port: strconv.Itoa(port),
Ndots: clientConfig.Ndots,
Timeout: 1,
}
for _, s := range strings.Split(clientConfig.Search[0], ".") {
filename = filepath.Join("/", "etc", "resolver", s)
_ = ioutil.WriteFile(filename, []byte(toString(config)), 0644)
}
}
func usingNetworkSetup(ip string, namespace string) {
networkSetup(ip, namespace)
var ctx context.Context
ctx, cancel = context.WithCancel(context.TODO())
go func() {
ticker := time.NewTicker(time.Second * 10)
newWatcher, _ := fsnotify.NewWatcher()
defer newWatcher.Close()
defer ticker.Stop()
_ = newWatcher.Add(resolv)
c := make(chan struct{}, 1)
c <- struct{}{}
for {
select {
case <-ticker.C:
c <- struct{}{}
case /*e :=*/ <-newWatcher.Events:
//if e.Op == fsnotify.Write {
c <- struct{}{}
//}
case <-c:
if rc, err := miekgdns.ClientConfigFromFile(resolv); err == nil && rc.Timeout != 1 {
if !sets.NewString(rc.Servers...).Has(ip) {
rc.Servers = append(rc.Servers, ip)
for _, s := range []string{namespace + ".svc.cluster.local", "svc.cluster.local", "cluster.local"} {
rc.Search = append(rc.Search, s)
}
//rc.Ndots = 5
}
//rc.Attempts = 1
rc.Timeout = 1
_ = ioutil.WriteFile(resolv, []byte(toString(*rc)), 0644)
}
case <-ctx.Done():
return
}
}
}()
}
func toString(config miekgdns.ClientConfig) string {
var builder strings.Builder
// builder.WriteString(`#
//# macOS Notice
//#
//# This file is not consulted for DNS hostname resolution, address
//# resolution, or the DNS query routing mechanism used by most
//# processes on this system.
//#
//# To view the DNS configuration used by this system, use:
//# scutil --dns
//#
//# SEE ALSO
//# dns-sd(1), scutil(8)
//#
//# This file is automatically generated.
//#`)
// builder.WriteString("\n")
if len(config.Search) > 0 {
builder.WriteString(fmt.Sprintf("search %s\n", strings.Join(config.Search, " ")))
}
for i := range config.Servers {
builder.WriteString(fmt.Sprintf("nameserver %s\n", config.Servers[i]))
}
if len(config.Port) != 0 {
builder.WriteString(fmt.Sprintf("port %s\n", config.Port))
}
builder.WriteString(fmt.Sprintf("options ndots:%d\n", config.Ndots))
builder.WriteString(fmt.Sprintf("options timeout:%d\n", config.Timeout))
//builder.WriteString(fmt.Sprintf("options attempts:%d\n", config.Attempts))
return builder.String()
}
func CancelDNS() {
if cancel != nil {
cancel()
}
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
//networkCancel()
}
/*
➜ resolver sudo networksetup -setdnsservers Wi-Fi 172.20.135.131 1.1.1.1
➜ resolver sudo networksetup -setsearchdomains Wi-Fi test.svc.cluster.local svc.cluster.local cluster.local
➜ resolver sudo networksetup -getsearchdomains Wi-Fi
test.svc.cluster.local
svc.cluster.local
cluster.local
➜ resolver sudo networksetup -getdnsservers Wi-Fi
172.20.135.131
1.1.1.1
*/
func networkSetup(ip string, namespace string) {
networkCancel()
b, err := exec.Command("networksetup", "-listallnetworkservices").Output()
if err != nil {
return
}
services := strings.Split(string(b), "\n")
for _, s := range services[:len(services)-1] {
cmd := exec.Command("networksetup", "-getdnsservers", s)
output, err := cmd.Output()
if err == nil {
var nameservers []string
if strings.Contains(string(output), "There aren't any DNS Servers") {
nameservers = make([]string, 0, 0)
// fix networksetup -getdnsservers is empty, but resolv.conf nameserver is not empty
if rc, err := miekgdns.ClientConfigFromFile(resolv); err == nil {
nameservers = rc.Servers
}
} else {
nameservers = strings.Split(string(output), "\n")
nameservers = nameservers[:len(nameservers)-1]
}
// add to tail
nameservers = append(nameservers, ip)
args := []string{"-setdnsservers", s}
output, err = exec.Command("networksetup", append(args, nameservers...)...).Output()
if err != nil {
log.Warnf("error while set dnsserver for %s, err: %v, output: %s\n", s, err, string(output))
}
}
output, err = exec.Command("networksetup", "-getsearchdomains", s).Output()
if err == nil {
var searchDomains []string
if strings.Contains(string(output), "There aren't any Search Domains") {
searchDomains = make([]string, 0, 0)
} else {
searchDomains = strings.Split(string(output), "\n")
searchDomains = searchDomains[:len(searchDomains)-1]
}
newSearchDomains := make([]string, len(searchDomains)+3, len(searchDomains)+3)
copy(newSearchDomains[3:], searchDomains)
newSearchDomains[0] = fmt.Sprintf("%s.svc.cluster.local", namespace)
newSearchDomains[1] = "svc.cluster.local"
newSearchDomains[2] = "cluster.local"
args := []string{"-setsearchdomains", s}
bytes, err := exec.Command("networksetup", append(args, newSearchDomains...)...).Output()
if err != nil {
log.Warnf("error while set search domain for %s, err: %v, output: %s\n", s, err, string(bytes))
}
}
}
}
func networkCancel() {
b, err := exec.Command("networksetup", "-listallnetworkservices").CombinedOutput()
if err != nil {
return
}
services := strings.Split(string(b), "\n")
for _, s := range services[:len(services)-1] {
output, err := exec.Command("networksetup", "-getsearchdomains", s).Output()
if err == nil {
i := strings.Split(string(output), "\n")
if i[1] == "svc.cluster.local" && i[2] == "cluster.local" {
bytes, err := exec.Command("networksetup", "-setsearchdomains", s, strings.Join(i[3:], " ")).Output()
if err != nil {
log.Warnf("error while remove search domain for %s, err: %v, output: %s\n", s, err, string(bytes))
}
output, err := exec.Command("networksetup", "-getdnsservers", s).Output()
if err == nil {
dnsServers := strings.Split(string(output), "\n")
// dnsServers[len(dnsServers)-1]=""
// dnsServers[len(dnsServers)-2]="ip which added by KubeVPN"
dnsServers = dnsServers[:len(dnsServers)-2]
if len(dnsServers) == 0 {
// set default dns server to 1.1.1.1 or just keep on empty
dnsServers = append(dnsServers, "empty")
}
args := []string{"-setdnsservers", s}
combinedOutput, err := exec.Command("networksetup", append(args, dnsServers...)...).Output()
if err != nil {
log.Warnf("error while remove dnsserver for %s, err: %v, output: %s\n", s, err, string(combinedOutput))
}
}
}
}
}
}

View File

@@ -1,77 +0,0 @@
//go:build windows
// +build windows
package dns
import (
"context"
"fmt"
miekgdns "github.com/miekg/dns"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"net"
"os"
"os/exec"
"strconv"
)
func SetupDNS(config *miekgdns.ClientConfig) error {
getenv := os.Getenv("luid")
parseUint, err := strconv.ParseUint(getenv, 10, 64)
if err != nil {
log.Warningln(err)
return err
}
luid := winipcfg.LUID(parseUint)
err = luid.SetDNS(windows.AF_INET, []net.IP{net.ParseIP(config.Servers[0])}, config.Search)
_ = exec.CommandContext(context.Background(), "ipconfig", "/flushdns").Run()
if err != nil {
log.Warningln(err)
return err
}
//_ = updateNicMetric(tunName)
_ = addNicSuffixSearchList(config.Search)
return nil
}
func CancelDNS() {
getenv := os.Getenv("luid")
parseUint, err := strconv.ParseUint(getenv, 10, 64)
if err != nil {
log.Warningln(err)
return
}
luid := winipcfg.LUID(parseUint)
_ = luid.FlushDNS(windows.AF_INET)
}
func updateNicMetric(name string) error {
cmd := exec.Command("PowerShell", []string{
"Set-NetIPInterface",
"-InterfaceAlias",
fmt.Sprintf("\"%s\"", name),
"-InterfaceMetric",
"1",
}...)
out, err := cmd.CombinedOutput()
if err != nil {
log.Warnf("error while update nic metrics, error: %v, output: %s, command: %v", err, string(out), cmd.Args)
}
return err
}
// @see https://docs.microsoft.com/en-us/powershell/module/dnsclient/set-dnsclientglobalsetting?view=windowsserver2019-ps#example-1--set-the-dns-suffix-search-list
func addNicSuffixSearchList(search []string) error {
cmd := exec.Command("PowerShell", []string{
"Set-DnsClientGlobalSetting",
"-SuffixSearchList",
fmt.Sprintf("@(\"%s\", \"%s\", \"%s\")", search[0], search[1], search[2]),
}...)
output, err := cmd.CombinedOutput()
log.Info(cmd.Args)
if err != nil {
log.Warnf("error while set dns suffix search list, err: %v, output: %s, command: %v", err, string(output), cmd.Args)
}
return err
}

View File

@@ -1,66 +0,0 @@
package dns
import (
miekgdns "github.com/miekg/dns"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/cache"
"strings"
)
type server struct {
// todo using cache to speed up dns resolve process
dnsCache *cache.LRUExpireCache
forwardDNS *miekgdns.ClientConfig
}
func NewDNSServer(network, address string, forwardDNS *miekgdns.ClientConfig) error {
return miekgdns.ListenAndServe(address, network, &server{
dnsCache: cache.NewLRUExpireCache(1000), forwardDNS: forwardDNS,
})
}
// ServeDNS consider using a cache
/*
nameserver 172.20.135.131
search nocalhost.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
*/
func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
q := r.Question
r.Question = make([]miekgdns.Question, 0, len(q))
question := q[0]
name := question.Name
switch strings.Count(question.Name, ".") {
case 1:
question.Name = question.Name + s.forwardDNS.Search[0] + "."
case 2:
question.Name = question.Name + s.forwardDNS.Search[1] + "."
case 3:
question.Name = question.Name + s.forwardDNS.Search[2] + "."
case 4:
question.Name = question.Name + strings.Split(s.forwardDNS.Search[2], ".")[1] + "."
case 5:
}
r.Question = []miekgdns.Question{question}
answer, err := miekgdns.Exchange(r, s.forwardDNS.Servers[0]+":53")
if err != nil {
log.Warnln(err)
err = w.WriteMsg(r)
if err != nil {
log.Warnln(err)
}
} else {
if len(answer.Answer) != 0 {
answer.Answer[0].Header().Name = name
}
if len(answer.Question) != 0 {
answer.Question[0].Name = name
}
err = w.WriteMsg(answer)
if err != nil {
log.Warnln(err)
}
}
}

View File

@@ -1,27 +0,0 @@
package dns
import (
"fmt"
miekgdns "github.com/miekg/dns"
"github.com/wencaiwulue/kubevpn/util"
"strconv"
"testing"
"time"
)
func TestSetupDnsServer(t *testing.T) {
port := util.GetAvailableUDPPortOrDie()
fmt.Println(port)
go func() {
err := NewDNSServer("udp", "127.0.0.1:"+strconv.Itoa(port), &miekgdns.ClientConfig{
Servers: []string{""},
Search: []string{"test.svc.cluster.local", "svc.cluster.local", "cluster.local"},
Port: "53",
Ndots: 0,
})
if err != nil {
t.FailNow()
}
}()
time.Sleep(time.Second * 5)
}

View File

@@ -1,2 +0,0 @@
FROM scratch
COPY envoy-xds-server /bin/envoy-xds-server

View File

@@ -1,6 +0,0 @@
FROM envoyproxy/envoy-dev:5f7d6efb5786ee3de31b1fb37c78fa281718b704
WORKDIR /app
RUN sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl net-tools iptables iputils-ping lsof iproute2

View File

@@ -1,6 +0,0 @@
FROM ubuntu:latest
WORKDIR /app
RUN sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl net-tools iptables iputils-ping lsof iproute2
COPY ./kubevpn /usr/local/bin/kubevpn

45
docs/en/Architecture.md Normal file
View File

@@ -0,0 +1,45 @@
## Architecture
### Connect mode
create a tunnel with port-forward, add route to virtual interface, like tun0, forward traffic though tunnel to remote
traffic manager.
![connect-mode](/docs/en/images/connect-mode.drawio.svg)
### Reverse mode
base on connect mode, inject a container to controller, use iptables to block all inbound traffic and forward to local
though tunnel.
```text
┌──────────┐ ┌─────────┌──────────┐ ┌──────────┐
│ ServiceA ├───►│ sidecar │ ServiceB │ ┌─►│ ServiceC │
└──────────┘ └────┌────┘──────────┘ │ └──────────┘
│ │
│ │ cloud
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘─ ─ ─ ─ ─ ─ ─ ─ ─┘ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ │ local
┌───┘──────┐ │
│ ServiceB'├──────────┘
└──────────┘
```
### Mesh mode
base on reverse mode, using envoy as proxy, if headers have special key-value pair, it will route to local machine, if
not, use origin service.
```text
┌──────────┐ ┌─────────┌────────────┐ ┌──────────┐
│ ServiceA ├───►│ sidecar ├─► ServiceB │─►┌─►│ ServiceC │
└──────────┘ └────┌────┘────────────┘ │ └──────────┘
│ │ cloud
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ │ local
header: foo=bar │
┌───┘──────┐ │
│ ServiceB'├─────────────┘
└──────────┘
```
![arch.svg](/docs/en/images/proxy-arch.svg)

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 106 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 372 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 488 KiB

View File

@@ -1,62 +0,0 @@
package driver
import (
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/driver/openvpn"
"github.com/wencaiwulue/kubevpn/driver/wintun"
"k8s.io/client-go/util/retry"
"os"
"os/exec"
"path/filepath"
)
func InstallTunTapDriver() {
if err := retry.OnError(retry.DefaultRetry, func(err error) bool {
return err != nil
}, func() error {
return openvpn.Install()
}); err != nil {
log.Warn(err)
}
}
func InstallWireGuardTunDriver() {
if err := retry.OnError(retry.DefaultRetry, func(err error) bool {
return err != nil
}, func() error {
return wintun.InstallWintunDriver()
}); err != nil {
log.Warn(err)
}
}
func UninstallWireGuardTunDriver() error {
wd, err := os.Getwd()
if err != nil {
return err
}
filename := filepath.Join(wd, "wintun.dll")
return os.Remove(filename)
}
func UninstallTunTapDriver() {
filepath.VolumeName("C")
path := filepath.Join(getDiskName()+":\\", "Program Files", "TAP-Windows", "Uninstall.exe")
cmd := exec.Command(path, "/S")
b, e := cmd.CombinedOutput()
if e != nil {
log.Warn(e)
}
log.Info(string(b))
}
func getDiskName() string {
for _, drive := range "ABCDEFGHIJKLMNOPQRSTUVWXYZ" {
f, err := os.Open(string(drive) + ":\\")
if err == nil {
_ = f.Close()
return string(drive)
}
}
return ""
}

View File

@@ -1,12 +0,0 @@
//go:build !windows
// +build !windows
package openvpn
import (
"errors"
)
func Install() error {
return errors.New("not need to implement")
}

View File

@@ -1,35 +0,0 @@
//go:build windows
// +build windows
package openvpn
import (
"embed"
"io/ioutil"
"os"
"os/exec"
)
//go:embed exe/tap-windows-9.21.2.exe
var fs embed.FS
// driver download from https://build.openvpn.net/downloads/releases/
func Install() error {
bytes, err := fs.ReadFile("exe/tap-windows-9.21.2.exe")
if err != nil {
return err
}
tempFile, err := ioutil.TempFile("", "*.exe")
defer func() { _ = os.Remove(tempFile.Name()) }()
if err != nil {
return err
}
if _, err = tempFile.Write(bytes); err != nil {
return err
}
_ = tempFile.Sync()
_ = tempFile.Close()
_ = os.Chmod(tempFile.Name(), 0700)
cmd := exec.Command(tempFile.Name(), "/S")
return cmd.Run()
}

View File

@@ -1,29 +0,0 @@
//go:build windows && amd64
// +build windows,amd64
package wintun
import (
"embed"
"io/ioutil"
"os"
"path/filepath"
)
//go:embed bin/amd64/wintun.dll
var wintunFs embed.FS
func InstallWintunDriver() error {
bytes, err := wintunFs.ReadFile("bin/amd64/wintun.dll")
if err != nil {
return err
}
executable, err := os.Executable()
if err != nil {
return err
}
filename := filepath.Join(filepath.Dir(executable), "wintun.dll")
_ = os.Remove(filename)
err = ioutil.WriteFile(filename, bytes, 644)
return err
}

View File

@@ -1,29 +0,0 @@
//go:build windows && arm
// +build windows,arm
package wintun
import (
"embed"
"io/ioutil"
"os"
"path/filepath"
)
//go:embed bin/arm/wintun.dll
var wintunFs embed.FS
func InstallWintunDriver() error {
bytes, err := wintunFs.ReadFile("bin/arm/wintun.dll")
if err != nil {
return err
}
executable, err := os.Executable()
if err != nil {
return err
}
filename := filepath.Join(filepath.Dir(executable), "wintun.dll")
_ = os.Remove(filename)
err = ioutil.WriteFile(filename, bytes, 644)
return err
}

View File

@@ -1,29 +0,0 @@
//go:build windows && arm64
// +build windows,arm64
package wintun
import (
"embed"
"io/ioutil"
"os"
"path/filepath"
)
//go:embed bin/arm64/wintun.dll
var wintunFs embed.FS
func InstallWintunDriver() error {
bytes, err := wintunFs.ReadFile("bin/arm64/wintun.dll")
if err != nil {
return err
}
executable, err := os.Executable()
if err != nil {
return err
}
filename := filepath.Join(filepath.Dir(executable), "wintun.dll")
_ = os.Remove(filename)
err = ioutil.WriteFile(filename, bytes, 644)
return err
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,10 +0,0 @@
//go:build !windows
// +build !windows
package wintun
import "github.com/pkg/errors"
func InstallWintunDriver() error {
return errors.New("not implement")
}

Some files were not shown because too many files have changed in this diff Show More