Compare commits

...

29 Commits

Author SHA1 Message Date
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
29 changed files with 943 additions and 116 deletions

View File

@@ -26,8 +26,8 @@ jobs:
release_name: Release ${{ github.ref }}
body: |
Changes in this Release
- First Change
- Second Change
- Fix known bugs
- Optimize code
draft: false
prerelease: false
@@ -48,38 +48,15 @@ jobs:
with:
name: UPLOAD_URL
path: UPLOAD_URL
- name: Build kubevpn-linux
run: make kubevpn-linux
- 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
asset_name: kubevpn-linux-amd64
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 }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: kubevpn
asset_name: kubevpn-darwin-amd64
asset_content_type: application/octet-stream
- name: Push image to docker hub
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USER }} --password-stdin
make all-image
- name: Build kubevpn-windows
run: make kubevpn-windows
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v1
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
token: ${{ secrets.REPOSITORYDISPATCH }}
event-type: release-event
client-payload: '{"url": "${{ steps.create_release.outputs.upload_url }}", "tag": "${{ github.ref }}"}'

View File

@@ -1,4 +1,4 @@
name: Go
name: Test
on:
push:
@@ -31,7 +31,7 @@ jobs:
run: kubectl apply -f https://raw.githubusercontent.com/wencaiwulue/kubevpn/master/samples/bookinfo.yaml
- name: Build
run: make kubevpn-linux
run: make kubevpn-linux-amd64
- name: Wait for pods reviews to be ready
run: |
@@ -54,26 +54,33 @@ jobs:
with:
go-version: 1.17
- uses: docker-practice/actions-setup-docker@master
- run: |
- name: Pull image in advance
run: |
rm '/usr/local/bin/kubectl'
set -x
docker version
docker pull naison/kubevpn:v2
docker pull naison/kubevpnmesh:v2
docker run --rm hello-world
- run: |
- name: Install minikube
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
run: make kubevpn-darwin-amd64
- name: Wait for pods reviews to be ready
run: |
@@ -81,6 +88,7 @@ jobs:
kubectl get all -o wide
kubectl get nodes -o yaml
ifconfig
netstat -anr
- name: Test
run: go test -v ./test/
@@ -94,13 +102,14 @@ jobs:
# uses: actions/setup-go@v2
# with:
# go-version: 1.17
# - uses: docker-practice/actions-setup-docker@master
# # - run: |
# # choco install docker-desktop
# # docker version
# # docker run --rm hello-world
# - run: |
# docker version
# docker run --rm hello-world
# - run: |
# winget install minikube
# minikube start --driver=docker
# choco install virtualbox
# choco install minikube
# minikube start --driver=virtualbox
# minikube kubectl -- get po -A
# choco install make
# - name: Kubernetes info

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

@@ -0,0 +1,44 @@
name: Upload release
on:
repository_dispatch:
types: [ release-event ]
jobs:
build:
name: Create Release
runs-on: ubuntu-latest
strategy:
matrix:
os-arch: [
kubevpn-darwin-amd64,
kubevpn-darwin-arm64,
kubevpn-windows-amd64.exe,
kubevpn-windows-arm64.exe,
kubevpn-windows-386.exe,
kubevpn-linux-amd64,
kubevpn-linux-arm64,
kubevpn-linux-386,
]
steps:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Checkout code
uses: actions/checkout@v2
- name: Build kubevpn-all-arch
run: |
git tag ${{ github.event.client_payload.tag }} || true
make all-kubevpn
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.client_payload.url }}
asset_path: ${{ matrix.os-arch }}
asset_name: ${{ matrix.os-arch }}
asset_content_type: application/octet-stream

103
Makefile
View File

@@ -1,37 +1,96 @@
.PHONY: kubevpn-macos
kubevpn-macos:
go build -o kubevpn github.com/wencaiwulue/kubevpn/cmd/kubevpn
chmod +x kubevpn
cp kubevpn /usr/local/bin/kubevpn
# These are the values we want to pass for VERSION and BUILD
VERSION := $(shell git tag -l --sort=v:refname | tail -1)
GIT_COMMIT := $(shell git describe --match=NeVeRmAtCh --always --abbrev=40)
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
FOLDER := github.com/wencaiwulue/kubevpn/cmd/kubevpn
CONTROL_PLANE_FOLDER := github.com/wencaiwulue/kubevpn/pkg/controlplane/cmd/server
.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 "-w -s \
-X ${FOLDER}/cmds.Version=${VERSION} \
-X ${FOLDER}/cmds.BuildTime=${BUILD_TIME} \
-X ${FOLDER}/cmds.GitCommit=${GIT_COMMIT} \
-X ${FOLDER}/cmds.Branch=${BRANCH} \
-X ${FOLDER}/cmds.OsArch=${OS_ARCH} \
"
.PHONY: all
all: all-kubevpn all-image
.PHONY: all-kubevpn
all-kubevpn: 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: all-image
all-image: image image-mesh image-control-plane
# ---------darwin-----------
.PHONY: kubevpn-darwin-amd64
kubevpn-darwin-amd64:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build ${LDFLAGS} -o kubevpn-darwin-amd64 ${FOLDER}
chmod +x kubevpn-darwin-amd64
cp kubevpn-darwin-amd64 /usr/local/bin/kubevpn
.PHONY: kubevpn-darwin-arm64
kubevpn-darwin-arm64:
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build ${LDFLAGS} -o kubevpn-darwin-arm64 ${FOLDER}
chmod +x kubevpn-darwin-arm64
cp kubevpn-darwin-arm64 /usr/local/bin/kubevpn
# ---------darwin-----------
# ---------windows-----------
.PHONY: kubevpn-windows-amd64
kubevpn-windows-amd64:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build ${LDFLAGS} -o kubevpn-windows-amd64.exe ${FOLDER}
.PHONY: kubevpn-windows-arm64
kubevpn-windows-arm64:
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build ${LDFLAGS} -o kubevpn-windows-arm64.exe ${FOLDER}
.PHONY: kubevpn-windows-386
kubevpn-windows-386:
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build ${LDFLAGS} -o kubevpn-windows-386.exe ${FOLDER}
# ---------windows-----------
# ---------linux-----------
.PHONY: kubevpn-linux-amd64
kubevpn-linux-amd64:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ${LDFLAGS} -o kubevpn-linux-amd64 ${FOLDER}
chmod +x kubevpn-linux-amd64
cp kubevpn-linux-amd64 /usr/local/bin/kubevpn
.PHONY: kubevpn-linux-arm64
kubevpn-linux-arm64:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ${LDFLAGS} -o kubevpn-linux-arm64 ${FOLDER}
chmod +x kubevpn-linux-arm64
cp kubevpn-linux-arm64 /usr/local/bin/kubevpn
.PHONY: kubevpn-linux-386
kubevpn-linux-386:
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build ${LDFLAGS} -o kubevpn-linux-386 ${FOLDER}
chmod +x kubevpn-linux-386
cp kubevpn-linux-386 /usr/local/bin/kubevpn
# ---------linux-----------
.PHONY: image
image: kubevpn-linux
image: kubevpn-linux-amd64
mv kubevpn-linux-amd64 kubevpn
docker build -t naison/kubevpn:v2 -f ./dockerfile/server/Dockerfile .
rm -fr kubevpn
docker push naison/kubevpn:v2
.PHONY: image_mesh
image_mesh:
.PHONY: image-mesh
image-mesh:
docker build -t naison/kubevpnmesh:v2 -f ./dockerfile/mesh/Dockerfile .
docker push naison/kubevpnmesh:v2
.PHONY: image_control_plane
image_control_plane: control-plane-linux
.PHONY: image-control-plane
image-control-plane:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o envoy-xds-server ${CONTROL_PLANE_FOLDER}
chmod +x envoy-xds-server
docker build -t naison/envoy-xds-server:latest -f ./dockerfile/controlplane/Dockerfile .
rm -fr envoy-xds-server
docker push naison/envoy-xds-server:latest

View File

@@ -10,9 +10,9 @@ kubernetes cluster service can also access your local service
```shell
git clone https://github.com/wencaiwulue/kubevpn.git
cd kubevpn
make kubevpn-linux
make kubevpn-macos
make kubevpn-windows
make kubevpn-linux-amd64
make kubevpn-darwin-amd64
make kubevpn-windows-amd64
```
if you are using windows, you can build by this command:
@@ -156,7 +156,7 @@ func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
_, _ = io.WriteString(writer, "Hello world!")
})
_ = http.ListenAndServe(":8080", nil)
_ = http.ListenAndServe(":9080", nil)
}
```
@@ -222,4 +222,4 @@ Hello world!%
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
in advance

View File

@@ -9,9 +9,9 @@
```shell
git clone https://github.com/wencaiwulue/kubevpn.git
cd kubevpn
make kubevpn-linux
make kubevpn-macos
make kubevpn-windows
make kubevpn-linux-amd64
make kubevpn-darwin-amd64
make kubevpn-windows-amd64
```
如果你在使用 Windows 系统,可以使用下面这条命令构建:

View File

@@ -11,14 +11,14 @@
- [ ] 考虑是否需要把 openvpn tap/tun 驱动作为后备方案
- [x] 加入 TLS 以提高安全性
- [ ] 写个 CNI 网络插件,直接提供 VPN 功能
- [ ] 优化重连逻辑
- [x] 优化重连逻辑
- [x] 支持 service mesh
- [ ] service mesh 支持多端口
- [x] 使用自己写的 proxy 替换 envoy
- [ ] 优化性能Windows 上考虑使用 IPC 通信
- [x] 自己写个 control plane
- [ ] 考虑是否将 control plane 和服务分开
- [ ] 写单元测试,优化 GitHub action
- [x] 写单元测试,优化 GitHub action
- [ ] Linux 和 macOS 也改用 WireGuard library
- [ ] 探测是否有重复路由的 utun设备禁用 `sudo ifconfig utun1 down`
- [x] 探测是否有重复路由的 utun设备禁用 `sudo ifconfig utun1 down`

View File

@@ -29,6 +29,12 @@ var connectCmd = &cobra.Command{
Use: "connect",
Short: "connect",
Long: `connect`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if !util.IsAdmin() {
util.RunWithElevated()
os.Exit(0)
}
},
PreRun: func(*cobra.Command, []string) {
util.InitLogger(util.Debug)
if util.IsWindows() {

View File

@@ -0,0 +1,51 @@
package cmds
import (
"fmt"
"github.com/spf13/cobra"
"runtime"
"runtime/debug"
"time"
)
// --ldflags -X
var (
Version = ""
OsArch = ""
GitCommit = ""
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
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of KubeVPN",
Long: `This is the version of KubeVPN`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("KubeVPN: CLI\n")
fmt.Printf(" Version: %s\n", Version)
fmt.Printf(" Branch: %s\n", Branch)
fmt.Printf(" Git commit: %s\n", 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())
},
}
func init() {
RootCmd.AddCommand(versionCmd)
// Prefer version number inserted at build using --ldflags
if Version == "" {
if i, ok := debug.ReadBuildInfo(); ok {
Version = i.Main.Version
}
}
}

View File

@@ -3,18 +3,13 @@ package main
import (
log "github.com/sirupsen/logrus"
"github.com/wencaiwulue/kubevpn/cmd/kubevpn/cmds"
"github.com/wencaiwulue/kubevpn/util"
"net/http"
_ "net/http/pprof"
)
func main() {
if !util.IsAdmin() {
util.RunWithElevated()
} else {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
_ = cmds.RootCmd.Execute()
}
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
_ = cmds.RootCmd.Execute()
}

View File

@@ -5,6 +5,7 @@ import (
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/cache"
"strings"
"time"
)
type server struct {
@@ -44,7 +45,9 @@ func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
case 5:
}
r.Question = []miekgdns.Question{question}
answer, err := miekgdns.Exchange(r, s.forwardDNS.Servers[0]+":53")
client := miekgdns.Client{Net: "udp", Timeout: time.Second * 5}
answer, _, err := client.Exchange(r, s.forwardDNS.Servers[0]+":53")
//answer, err := miekgdns.Exchange(r, s.forwardDNS.Servers[0]+":53")
if err != nil {
log.Warnln(err)
err = w.WriteMsg(r)

View File

@@ -3,4 +3,4 @@ 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
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl net-tools iptables iputils-ping lsof iproute2 tcpdump

View File

@@ -2,5 +2,5 @@ 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
RUN apt-get clean && apt-get update && apt-get install -y wget dnsutils vim curl net-tools iptables iputils-ping lsof iproute2 tcpdump
COPY ./kubevpn /usr/local/bin/kubevpn

View File

@@ -1,5 +1,6 @@
//go:build windows && x86
// +build windows,x86
//go:build windows && (x86 || 386)
// +build windows
// +build x86 386
package wintun

8
go.mod
View File

@@ -19,8 +19,8 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
github.com/spf13/cobra v1.1.3
golang.org/x/net v0.0.0-20211111083644-e5c967477495
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
golang.zx2c4.com/wireguard v0.0.0-20211209221555-9c9e7e272434
golang.zx2c4.com/wireguard/windows v0.4.10
google.golang.org/appengine v1.6.7 // indirect
@@ -33,6 +33,7 @@ require (
k8s.io/client-go v0.21.2
k8s.io/klog/v2 v2.10.0 // indirect
k8s.io/kubectl v0.21.2
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
)
require (
@@ -81,7 +82,7 @@ require (
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
@@ -90,7 +91,6 @@ require (
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
k8s.io/component-base v0.21.2 // indirect
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 // indirect
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect
sigs.k8s.io/kustomize/api v0.8.8 // indirect
sigs.k8s.io/kustomize/kyaml v0.10.17 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 // indirect

9
go.sum
View File

@@ -874,8 +874,9 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211111083644-e5c967477495 h1:cjxxlQm6d4kYbhpZ2ghvmI8xnq0AG+jXmzrhzfkyu5A=
golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -966,12 +967,14 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 h1:WecRHqgE09JBkh/584XIE6PMz5KKE/vER4izNUi30AQ=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@@ -17,6 +17,7 @@ import (
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/polymorphichelpers"
"net"
"os"
"strings"
"time"
)
@@ -116,6 +117,7 @@ func (c *ConnectOptions) DoConnect() (err error) {
return err
}
c.deleteFirewallRuleAndSetupDNS(ctx)
c.detectConflictDevice()
return
}
@@ -212,6 +214,16 @@ func (c *ConnectOptions) deleteFirewallRuleAndSetupDNS(ctx context.Context) {
log.Info("dns service ok")
}
func (c *ConnectOptions) detectConflictDevice() {
tun := os.Getenv("tunName")
if len(tun) == 0 {
return
}
if err := DetectAndDisableConflictDevice(tun); err != nil {
log.Warnf("error occours while disable conflict devices, err: %v", err)
}
}
func (c *ConnectOptions) setupDNS() {
relovConf, err := dns.GetDNSServiceIPFromPod(c.clientset, c.restclient, c.config, util.TrafficManager, c.Namespace)
if err != nil {
@@ -245,18 +257,18 @@ func getCIDR(clientset *kubernetes.Clientset, namespace string) ([]*net.IPNet, e
var CIDRList []*net.IPNet
// get pod CIDR from node spec
if nodeList, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}); err == nil {
var podCIDRs = sets.NewString()
for _, node := range nodeList.Items {
var podCIDRs []string
if node.Spec.PodCIDRs != nil {
podCIDRs = append(podCIDRs, node.Spec.PodCIDRs...)
podCIDRs.Insert(node.Spec.PodCIDRs...)
}
if len(node.Spec.PodCIDR) != 0 {
podCIDRs = append(podCIDRs, node.Spec.PodCIDR)
podCIDRs.Insert(node.Spec.PodCIDR)
}
for _, podCIDR := range podCIDRs {
if _, CIDR, err := net.ParseCIDR(podCIDR); err == nil {
CIDRList = append(CIDRList, CIDR)
}
}
for _, podCIDR := range podCIDRs.List() {
if _, CIDR, err := net.ParseCIDR(podCIDR); err == nil {
CIDRList = append(CIDRList, CIDR)
}
}
}

View File

@@ -110,10 +110,10 @@ func UnPatchContainer(factory cmdutil.Factory, clientset *kubernetes.Clientset,
return err
}
port := uint32(templateSpec.Spec.Containers[0].Ports[0].ContainerPort)
//port := uint32(templateSpec.Spec.Containers[0].Ports[0].ContainerPort)
configMapName := fmt.Sprintf("%s-%s", object.Mapping.Resource.Resource, object.Name)
createEnvoyConfigMapIfNeeded(clientset, object.Namespace, configMapName, strconv.Itoa(int(port)))
//createEnvoyConfigMapIfNeeded(clientset, object.Namespace, configMapName, strconv.Itoa(int(port)))
err = removeEnvoyConfig(clientset, object.Namespace, configMapName, headers)
if err != nil {
log.Warnln(err)

View File

@@ -21,8 +21,15 @@ func RemoveContainers(spec *v1.PodTemplateSpec) {
}
}
for i := 0; i < len(spec.Spec.Containers); i++ {
for j := 0; j < len(spec.Spec.Containers[i].VolumeMounts); j++ {
if spec.Spec.Containers[i].VolumeMounts[j].Name == EnvoyConfig {
spec.Spec.Containers[i].VolumeMounts = append(spec.Spec.Containers[i].VolumeMounts[:j],
spec.Spec.Containers[i].VolumeMounts[j+1:]...)
}
}
if sets.NewString(EnvoyProxy, ControlPlane, VPN).Has(spec.Spec.Containers[i].Name) {
spec.Spec.Containers = append(spec.Spec.Containers[:i], spec.Spec.Containers[i+1:]...)
i--
}
}
}
@@ -38,6 +45,7 @@ func AddMeshContainer(spec *v1.PodTemplateSpec, configMapName string, c util.Pod
for i := 0; i < len(spec.Spec.Containers); i++ {
if sets.NewString(EnvoyProxy, ControlPlane, VPN).Has(spec.Spec.Containers[i].Name) {
spec.Spec.Containers = append(spec.Spec.Containers[:i], spec.Spec.Containers[i+1:]...)
i--
}
}
zero := int64(0)

56
pkg/network_interface.go Normal file
View File

@@ -0,0 +1,56 @@
package pkg
import (
"bytes"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/sets"
"net"
"strings"
)
// DetectAndDisableConflictDevice will detect conflict route table and try to disable device
// 1, get route table
// 2, detect conflict
// 3, disable device
func DetectAndDisableConflictDevice(origin string) error {
routeTable, err := getRouteTable()
if err != nil {
return err
}
conflict := detectConflictDevice(origin, routeTable)
if len(conflict) != 0 {
log.Infof("those device: %s will to be disabled because of route conflict with %s", strings.Join(conflict, ","), origin)
}
err = disableDevice(conflict)
return err
}
func detectConflictDevice(origin string, routeTable map[string][]*net.IPNet) []string {
var conflict = sets.NewString()
vpnRoute := routeTable[origin]
for k, originRoute := range routeTable {
if k == origin {
continue
}
out:
for _, originNet := range originRoute {
for _, vpnNet := range vpnRoute {
// like 255.255.0.0/16 should not take effect
if bytes.Equal(originNet.IP, originNet.Mask) || bytes.Equal(vpnNet.IP, vpnNet.Mask) {
continue
}
if vpnNet.Contains(originNet.IP) || originNet.Contains(vpnNet.IP) {
originMask, _ := originNet.Mask.Size()
vpnMask, _ := vpnNet.Mask.Size()
// means interface: k is more precisely, traffic will go to interface k because route table feature
// mare precisely is preferred
if originMask > vpnMask {
conflict.Insert(k)
break out
}
}
}
}
}
return conflict.Delete(origin).List()
}

View File

@@ -0,0 +1,156 @@
package pkg
import (
"fmt"
"net"
"syscall"
"testing"
"golang.org/x/net/route"
)
// netstat -anr | grep 10.61
//10.61/16 utun4 USc utun4
//10.61.10.251 10.176.32.40 UGHWIig utun2
//10.61.64/18 10.61.64.1 UCS utun3
//10.61.64.1 10.61.64.0 UH utun3
func TestConflict(t *testing.T) {
var mm = make(map[string][]*net.IPNet)
_, ipNet, err := net.ParseCIDR("10.61.0.0/16")
if err != nil {
panic(err)
}
_, ipNet2, err := net.ParseCIDR("10.61.64.0/18")
if err != nil {
panic(err)
}
_, ipNet3, err := net.ParseCIDR("10.61.64.1/24")
if err != nil {
panic(err)
}
mm["utun4"] = []*net.IPNet{ipNet}
mm["utun3"] = []*net.IPNet{ipNet2, ipNet3}
var origin = "utun4"
conflict := detectConflictDevice(origin, mm)
fmt.Println(conflict)
}
func TestGetConflictDevice(t *testing.T) {
err := DetectAndDisableConflictDevice("utun2")
if err != nil {
panic(err)
}
}
func TestParse(t *testing.T) {
rib, err := route.FetchRIB(syscall.AF_INET, syscall.NET_RT_DUMP, 0)
if err != nil {
panic(err)
}
msgs, err := route.ParseRIB(syscall.NET_RT_DUMP, rib)
if err != nil {
panic(err)
}
nameToIndex := make(map[int]string)
addrs, err := net.Interfaces()
for _, addr := range addrs {
nameToIndex[addr.Index] = addr.Name
}
m := make(map[string][]route.Addr)
for _, msg := range msgs {
message := msg.(*route.RouteMessage)
if name, found := nameToIndex[message.Index]; found {
if v, ok := m[name]; ok {
temp := removeEmptyElement(message)
m[name] = append(v, temp...)
} else {
m[name] = removeEmptyElement(message)
}
}
}
fmt.Println(m)
}
func removeEmptyElement(message *route.RouteMessage) []route.Addr {
var temp []route.Addr
for _, addr := range message.Addrs {
if addr != nil {
temp = append(temp, addr)
}
}
return temp
}
func TestGetRouteTableByNetstat(t *testing.T) {
ip := net.ParseIP("192.168.1.1")
for i := range ip.To4() {
fmt.Println(i)
}
}
func TestInteract(t *testing.T) {
type data struct {
ipNet1 *net.IPNet
ipNet2 *net.IPNet
result bool
}
var list = []data{{
ipNet1: &net.IPNet{
IP: net.ParseIP("192.168.1.1"),
Mask: net.CIDRMask(24, 32),
},
ipNet2: &net.IPNet{
IP: net.ParseIP("192.168.100.100"),
Mask: net.CIDRMask(16, 32),
},
result: true,
}, {
ipNet1: &net.IPNet{
IP: net.ParseIP("192.168.0.0"),
Mask: net.CIDRMask(17, 32),
},
ipNet2: &net.IPNet{
IP: net.ParseIP("192.168.0.0"),
Mask: net.CIDRMask(16, 32),
},
result: true,
}, {
ipNet1: &net.IPNet{
IP: net.ParseIP("191.168.0.0"),
Mask: net.CIDRMask(17, 32),
},
ipNet2: &net.IPNet{
IP: net.ParseIP("192.168.0.0"),
Mask: net.CIDRMask(16, 32),
},
result: false,
}, {
ipNet1: &net.IPNet{
IP: net.ParseIP("255.255.255.0"),
Mask: net.CIDRMask(24, 32),
},
ipNet2: &net.IPNet{
IP: net.ParseIP("255.255.0.0"),
Mask: net.CIDRMask(16, 32),
},
result: true,
}, {
ipNet1: &net.IPNet{
IP: net.ParseIP("255.255.255.255"),
Mask: net.CIDRMask(32, 32),
},
ipNet2: &net.IPNet{
IP: net.ParseIP("255.255.0.0"),
Mask: net.CIDRMask(16, 32),
},
result: false,
}}
for _, d := range list {
if b := d.ipNet1.Contains(d.ipNet2.IP) || d.ipNet2.Contains(d.ipNet1.IP); d.result != b {
t.FailNow()
}
}
}

View File

@@ -185,7 +185,7 @@ func CreateInboundPod(factory cmdutil.Factory, namespace, workloads string, conf
}})
_, err = helper.Patch(object.Namespace, object.Name, types.JSONPatchType, bytes, &metav1.PatchOptions{})
if err != nil {
log.Errorf("error while inject proxy container, err: %v, exiting...")
log.Errorf("error while inject proxy container, err: %v, exiting...", err)
return err
}
removePatch, restorePatch := patch(origin, path)

View File

@@ -247,3 +247,14 @@ func patchs(helper *pkgresource.Helper, namespace, name string, p []byte) (k8sru
&metav1.PatchOptions{},
)
}
func TestSliceRemove(t *testing.T) {
a := []string{"a", "a", "b", "c"}
for i := 0; i < len(a); i++ {
if a[i] == "a" {
a = append(a[:i], a[i+1:]...)
//i--
}
}
fmt.Println(a)
}

98
pkg/route_table_by_net.go Normal file
View File

@@ -0,0 +1,98 @@
//go:build !amd64 && !arm64 && !x86 && !386
// +build !amd64,!arm64,!x86,!386
package pkg
import (
"golang.org/x/net/route"
"net"
"syscall"
)
// not contains route like 10.61.64/18 10.61.64.1 UCS utun3, todo how about pull a merge to golang sdk???
// just contains 10.61.64, which mask is 0, 8, 16, 32, do not middle number
func getRouteTableByFetchRIB() (map[string][]*net.IPNet, error) {
rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_DUMP, 0)
if err != nil {
return nil, err
}
msgs, err := route.ParseRIB(syscall.NET_RT_DUMP, rib)
if err != nil {
return nil, err
}
nameToIndex := make(map[int]string)
addrs, err := net.Interfaces()
for _, addr := range addrs {
nameToIndex[addr.Index] = addr.Name
}
m := make(map[string][]route.Addr)
for _, msg := range msgs {
message := msg.(*route.RouteMessage)
if name, found := nameToIndex[message.Index]; found {
if v, ok := m[name]; ok {
temp := removeNilElement(message)
m[name] = append(v, temp...)
} else {
m[name] = removeNilElement(message)
}
}
}
var mm = make(map[string][]*net.IPNet)
for k, v := range m {
var temp []*net.IPNet
for _, addr := range v {
if a, ok := addr.(*route.Inet4Addr); ok {
var ip = make(net.IP, net.IPv4len)
copy(ip, a.IP[:])
if one, _ := mask(ip).Size(); one == 0 {
continue
}
temp = append(temp, &net.IPNet{IP: ip, Mask: mask(ip)})
} else if a, ok := addr.(*route.Inet6Addr); ok {
var ip = make(net.IP, net.IPv6len)
copy(ip, a.IP[:])
if one, _ := mask(ip).Size(); one == 0 {
continue
}
temp = append(temp, &net.IPNet{IP: ip, Mask: mask(ip)})
} else if _, ok := addr.(*route.LinkAddr); ok {
//fmt.Println(a)
// todo
}
}
mm[k] = temp
}
return mm, nil
}
func removeNilElement(message *route.RouteMessage) []route.Addr {
var temp []route.Addr
for _, addr := range message.Addrs {
if addr != nil {
temp = append(temp, addr)
}
}
return temp
}
// route.FetchRIB fetches a routing information base from the operating system.
// In most cases, zero means a wildcard.
func mask(ip []byte) net.IPMask {
size := 0
for i := len(ip) - 1; i >= 0; i-- {
if ip[i] == 0 {
size++
} else {
break
}
}
// 0.0.0.0
if size == len(ip) {
return net.CIDRMask(len(ip)*8, len(ip)*8)
}
if size == 0 {
return net.CIDRMask(0, len(ip)*8)
}
return net.CIDRMask((len(ip)-size)*8, len(ip)*8)
}

262
pkg/route_table_darwin.go Normal file
View File

@@ -0,0 +1,262 @@
//go:build darwin
// +build darwin
package pkg
import (
log "github.com/sirupsen/logrus"
"net"
"os/exec"
"strconv"
"strings"
)
// sudo ifconfig utun3 down
func disableDevice(conflict []string) error {
for _, dev := range conflict {
if err := exec.Command("sudo", "ifconfig", dev, "down").Run(); err != nil {
log.Errorf("can not disable interface: %s, err: %v", dev, err)
return err
} else {
rollbackFuncList = append(rollbackFuncList, func() {
_ = exec.Command("sudo", "ifconfig", dev, "up").Run()
})
}
}
return nil
}
func getRouteTable() (map[string][]*net.IPNet, error) {
output, err := exec.Command("netstat", "-anr").CombinedOutput()
if err != nil {
return nil, err
}
split := strings.Split(string(output), "\n")
routeTable := make(map[string][]*net.IPNet)
for _, i := range split {
fields := strings.Fields(i)
if len(fields) >= 4 {
cidr := fields[0]
eth := fields[3]
if _, ipNet, err := parseCIDR(cidr); err == nil {
if v, ok := routeTable[eth]; ok {
routeTable[eth] = append(v, ipNet)
} else {
routeTable[eth] = []*net.IPNet{ipNet}
}
}
}
}
return routeTable, nil
}
const big = 0xFFFFFF
// Decimal to integer.
// Returns number, characters consumed, success.
func dtoi(s string) (n int, i int, ok bool) {
n = 0
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
n = n*10 + int(s[i]-'0')
if n >= big {
return big, i, false
}
}
if i == 0 {
return 0, 0, false
}
return n, i, true
}
// Hexadecimal to integer.
// Returns number, characters consumed, success.
func xtoi(s string) (n int, i int, ok bool) {
n = 0
for i = 0; i < len(s); i++ {
if '0' <= s[i] && s[i] <= '9' {
n *= 16
n += int(s[i] - '0')
} else if 'a' <= s[i] && s[i] <= 'f' {
n *= 16
n += int(s[i]-'a') + 10
} else if 'A' <= s[i] && s[i] <= 'F' {
n *= 16
n += int(s[i]-'A') + 10
} else {
break
}
if n >= big {
return 0, i, false
}
}
if i == 0 {
return 0, i, false
}
return n, i, true
}
func parseCIDR(s string) (net.IP, *net.IPNet, error) {
indexByte6 := strings.Count(s, ":")
indexByte4 := strings.Count(s, ".")
if indexByte4 < 0 && indexByte6 < 0 {
return nil, nil, &net.ParseError{Type: "CIDR address", Text: s}
}
i := strings.IndexByte(s, '/')
var addr, mask string
if i < 0 {
addr = s
// ipv6
if indexByte6 > 0 {
mask = strconv.Itoa((indexByte6 + 1) * 8)
} else {
mask = strconv.Itoa((indexByte4 + 1) * 8)
}
} else {
addr, mask = s[:i], s[i+1:]
}
iplen := net.IPv4len
ip := parseIPv4(addr)
if ip == nil {
iplen = net.IPv6len
ip = parseIPv6(addr)
}
n, i, ok := dtoi(mask)
if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
return nil, nil, &net.ParseError{Type: "CIDR address", Text: s}
}
m := net.CIDRMask(n, 8*iplen)
return ip, &net.IPNet{IP: ip.Mask(m), Mask: m}, nil
}
// Parse IPv4 address (d.d.d.d).
func parseIPv4(s string) net.IP {
var p [net.IPv4len]byte
for i := 0; i < net.IPv4len; i++ {
if len(s) == 0 {
// Missing octets.
continue
}
if i > 0 {
if s[0] != '.' {
return nil
}
s = s[1:]
}
n, c, ok := dtoi(s)
if !ok || n > 0xFF {
return nil
}
if c > 1 && s[0] == '0' {
// Reject non-zero components with leading zeroes.
return nil
}
s = s[c:]
p[i] = byte(n)
}
if len(s) != 0 {
return nil
}
return net.IPv4(p[0], p[1], p[2], p[3])
}
func parseIPv6(s string) (ip net.IP) {
ip = make(net.IP, net.IPv6len)
ellipsis := -1 // position of ellipsis in ip
// Might have leading ellipsis
if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
ellipsis = 0
s = s[2:]
// Might be only ellipsis
if len(s) == 0 {
return ip
}
}
// Loop, parsing hex numbers followed by colon.
i := 0
for i < net.IPv6len {
// Hex number.
n, c, ok := xtoi(s)
if !ok || n > 0xFFFF {
i++
continue
}
// If followed by dot, might be in trailing IPv4.
if c < len(s) && s[c] == '.' {
if ellipsis < 0 && i != net.IPv6len-net.IPv4len {
// Not the right place.
return nil
}
if i+net.IPv4len > net.IPv6len {
// Not enough room.
return nil
}
ip4 := parseIPv4(s)
if ip4 == nil {
return nil
}
ip[i] = ip4[12]
ip[i+1] = ip4[13]
ip[i+2] = ip4[14]
ip[i+3] = ip4[15]
s = ""
i += net.IPv4len
break
}
// Save this 16-bit chunk.
ip[i] = byte(n >> 8)
ip[i+1] = byte(n)
i += 2
// Stop at end of string.
s = s[c:]
if len(s) == 0 {
break
}
// Otherwise must be followed by colon and more.
if s[0] != ':' || len(s) == 1 {
return nil
}
s = s[1:]
// Look for ellipsis.
if s[0] == ':' {
if ellipsis >= 0 { // already have one
return nil
}
ellipsis = i
s = s[1:]
if len(s) == 0 { // can be at end
break
}
}
}
// Must have used entire string.
if len(s) != 0 {
return nil
}
// If didn't parse enough, expand ellipsis.
if i < net.IPv6len {
if ellipsis < 0 {
return nil
}
n := net.IPv6len - i
for j := i - 1; j >= ellipsis; j-- {
ip[j+n] = ip[j]
}
for j := ellipsis + n - 1; j >= ellipsis; j-- {
ip[j] = 0
}
} else if ellipsis >= 0 {
// Ellipsis must represent at least one 0 group.
return nil
}
return ip
}

48
pkg/route_table_linux.go Normal file
View File

@@ -0,0 +1,48 @@
//go:build !windows && !darwin
// +build !windows,!darwin
package pkg
import (
"net"
"os/exec"
"strings"
)
func getRouteTable() (map[string][]*net.IPNet, error) {
output, err := exec.Command("route", "-n").CombinedOutput()
if err != nil {
return nil, err
}
split := strings.Split(string(output), "\n")
routeTable := make(map[string][]*net.IPNet)
for _, i := range split {
fields := strings.Fields(i)
if len(fields) >= 8 {
dst := net.ParseIP(fields[0])
mask := make(net.IPMask, net.IPv4len)
copy(mask, net.ParseIP(fields[2]))
eth := fields[7]
if v, ok := routeTable[eth]; ok {
routeTable[eth] = append(v, &net.IPNet{IP: dst, Mask: mask})
} else {
routeTable[eth] = []*net.IPNet{{IP: dst, Mask: mask}}
}
}
}
return routeTable, nil
}
func disableDevice(list []string) error {
for _, dev := range list {
if err := exec.Command("sudo", "ifconfig", dev, "down").Run(); err != nil {
return err
} else {
rollbackFuncList = append(rollbackFuncList, func() {
_ = exec.Command("sudo", "ifconfig", dev, "up").Run()
})
}
}
return nil
}

View File

@@ -0,0 +1,16 @@
//go:build windows
// +build windows
package pkg
import (
"net"
)
func getRouteTable() (map[string][]*net.IPNet, error) {
return make(map[string][]*net.IPNet), nil
}
func disableDevice(list []string) error {
return nil
}

View File

@@ -8,10 +8,12 @@ import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/retry"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"net"
"net/http"
@@ -33,6 +35,7 @@ var (
)
func TestFunctions(t *testing.T) {
kubevpnConnect()
t.Cleanup(cancelFunc)
t.Parallel()
t.Run(runtime.FuncForPC(reflect.ValueOf(pingPodIP).Pointer()).Name(), pingPodIP)
@@ -182,10 +185,14 @@ func dialUDP(t *testing.T) {
if len(ip) == 0 {
t.Errorf("can not found pods for service reviews")
}
time.Sleep(time.Second * 5)
log.Infof("dail udp to ip: %s", ip)
err = client(ip, port)
if err != nil {
log.Printf("dail udp to ip: %s", ip)
if err = retry.OnError(
wait.Backoff{Duration: time.Second, Factor: 2, Jitter: 0.2, Steps: 5},
func(err error) bool {
return err != nil
}, func() error {
return client(ip, port)
}); err != nil {
t.Errorf("can not access pod ip: %s, port: %v", ip, port)
}
}
@@ -201,6 +208,11 @@ func client(ip string, port int) error {
}
defer udpConn.Close()
err = udpConn.SetDeadline(time.Now().Add(time.Second * 30))
if err != nil {
return err
}
// 发送数据
sendData := []byte("hello server!")
_, err = udpConn.Write(sendData)
@@ -251,8 +263,7 @@ func server(port int) {
}
}
func init() {
initClient()
func kubevpnConnect() {
var ctx context.Context
ctx, cancelFunc = context.WithCancel(context.TODO())
childCtx, timeoutFunc := context.WithTimeout(ctx, time.Minute*10)
@@ -268,7 +279,7 @@ func init() {
<-childCtx.Done()
}
func initClient() {
func init() {
var err error
configFlags := genericclioptions.NewConfigFlags(true)

View File

@@ -37,6 +37,7 @@ func Listener(config Config) (net.Listener, error) {
if err != nil {
return nil, err
}
ln.addr = conn.LocalAddr()
addrs, _ := ifce.Addrs()