mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-12-24 11:51:13 +08:00
dhcp support rent ip
This commit is contained in:
@@ -14,12 +14,13 @@ func Windows(ip string) error {
|
||||
"interface",
|
||||
"ipv4",
|
||||
"add",
|
||||
"dnsserver",
|
||||
"dnsservers",
|
||||
fmt.Sprintf("name=\"%s\"", tunName),
|
||||
fmt.Sprintf("address=%s", ip),
|
||||
"index=2",
|
||||
"index=1",
|
||||
}
|
||||
output, err := exec.Command("netsh", args...).CombinedOutput()
|
||||
fmt.Println(exec.Command("netsh", args...).Args)
|
||||
log.Info(string(output))
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
|
||||
1
go.mod
1
go.mod
@@ -46,7 +46,6 @@ require (
|
||||
github.com/xtaci/tcpraw v1.2.25
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
|
||||
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d
|
||||
golang.zx2c4.com/wireguard v0.0.0-20210624150102-15b24b6179e0 // indirect
|
||||
k8s.io/api v0.21.2
|
||||
k8s.io/apimachinery v0.21.2
|
||||
k8s.io/cli-runtime v0.21.2
|
||||
|
||||
3
go.sum
3
go.sum
@@ -669,7 +669,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
||||
@@ -737,8 +736,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20210624150102-15b24b6179e0 h1:qINUmOnDCCF7i14oomDDkGmlda7BSDTGfge77/aqdfk=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20210624150102-15b24b6179e0/go.mod h1:laHzsbfMhGSobUmruXWAyMKKHSqvIcrqZJMyHD+/3O8=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
|
||||
@@ -70,7 +70,7 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) {
|
||||
}
|
||||
|
||||
if ip != nil && ipNet != nil {
|
||||
cmd := fmt.Sprintf("netsh interface ip set address name=%s "+
|
||||
cmd := fmt.Sprintf("netsh interface ip set address name=\"%s\" "+
|
||||
"source=static addr=%s mask=%s gateway=none",
|
||||
ifce.Name(), ip.String(), ipMask(ipNet.Mask))
|
||||
log.Log("[tap]", cmd)
|
||||
@@ -105,7 +105,7 @@ func addTunRoutes(ifName string, gw string, routes ...IPRoute) error {
|
||||
|
||||
deleteRoute(ifName, route.Dest.String())
|
||||
|
||||
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active",
|
||||
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=\"%s\" store=active",
|
||||
route.Dest.String(), ifName)
|
||||
if gw != "" {
|
||||
cmd += " nexthop=" + gw
|
||||
@@ -127,7 +127,7 @@ func addTapRoutes(ifName string, gw string, routes ...string) error {
|
||||
|
||||
deleteRoute(ifName, route)
|
||||
|
||||
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active",
|
||||
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=\"%s\" store=active",
|
||||
route, ifName)
|
||||
if gw != "" {
|
||||
cmd += " nexthop=" + gw
|
||||
@@ -142,7 +142,7 @@ func addTapRoutes(ifName string, gw string, routes ...string) error {
|
||||
}
|
||||
|
||||
func deleteRoute(ifName string, route string) error {
|
||||
cmd := fmt.Sprintf("netsh interface ip delete route prefix=%s interface=%s store=active",
|
||||
cmd := fmt.Sprintf("netsh interface ip delete route prefix=%s interface=\"%s\" store=active",
|
||||
route, ifName)
|
||||
args := strings.Split(cmd, " ")
|
||||
return exec.Command(args[0], args[1:]...).Run()
|
||||
|
||||
27
pkg/main.go
27
pkg/main.go
@@ -13,6 +13,7 @@ import (
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
"kubevpn/dns"
|
||||
"kubevpn/exe"
|
||||
"kubevpn/gost"
|
||||
"kubevpn/remote"
|
||||
"kubevpn/util"
|
||||
"net"
|
||||
@@ -28,7 +29,6 @@ var (
|
||||
clientset *kubernetes.Clientset
|
||||
restclient *rest.RESTClient
|
||||
config *rest.Config
|
||||
name string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -49,7 +49,9 @@ func init() {
|
||||
if namespace, _, err = factory.ToRawKubeConfigLoader().Namespace(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func prepare() {
|
||||
k8sCIDR, err := getCIDR(clientset, namespace)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -60,23 +62,26 @@ func init() {
|
||||
IP: net.IPv4(192, 168, 254, 100),
|
||||
Mask: net.IPv4Mask(255, 255, 255, 0),
|
||||
}
|
||||
name = remote.CreateServer(clientset, namespace, trafficManager.String())
|
||||
fmt.Println(name)
|
||||
err = remote.CreateServer(clientset, namespace, trafficManager.String())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = remote.InitDHCP(clientset, namespace, &net.IPNet{IP: net.IPv4(196, 168, 254, 100), Mask: net.IPv4Mask(255, 255, 255, 0)})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
dhcp, err := remote.GetIpFromDHCP(clientset, namespace)
|
||||
tunIp, err := remote.GetIpFromDHCP(clientset, namespace)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
remote.AddCleanUpResourceHandler(clientset, namespace, tunIp)
|
||||
//if runtime.GOOS == "windows" {
|
||||
dhcp.Mask = net.IPv4Mask(0, 0, 0, 0)
|
||||
tunIp.Mask = net.IPv4Mask(0, 0, 0, 0)
|
||||
//} else {
|
||||
// dhcp.Mask = net.IPv4Mask(255, 255, 255, 0)
|
||||
//}
|
||||
list = append(list, dhcp.String())
|
||||
list = append(list, tunIp.String())
|
||||
//if runtime.GOOS == "windows" {
|
||||
ipNet := net.IPNet{
|
||||
IP: net.IPv4(192, 168, 254, 100),
|
||||
@@ -87,10 +92,10 @@ func init() {
|
||||
|
||||
baseCfg.route.ChainNodes = []string{"ssh://127.0.0.1:2222"}
|
||||
baseCfg.route.ServeNodes = []string{
|
||||
fmt.Sprintf("tun://:8421/127.0.0.1:8421?net=%s&route=%s", dhcp.String(), strings.Join(list, ",")),
|
||||
fmt.Sprintf("tun://:8421/127.0.0.1:8421?net=%s&route=%s", tunIp.String(), strings.Join(list, ",")),
|
||||
}
|
||||
fmt.Println("your ip is " + dhcp.String())
|
||||
baseCfg.Debug = true
|
||||
fmt.Println("your ip is " + tunIp.String())
|
||||
gost.Debug = true
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
exe.InstallTunTapDriver()
|
||||
@@ -98,10 +103,12 @@ func init() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
prepare()
|
||||
|
||||
readyChan := make(chan struct{})
|
||||
stop := make(chan struct{})
|
||||
go func() {
|
||||
err := util.PortForwardPod(config, clientset, name, namespace, "2222:2222", readyChan, stop)
|
||||
err := util.PortForwardPod(config, clientset, remote.TrafficManager, namespace, "2222:2222", readyChan, stop)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
net2 "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
"kubevpn/remote"
|
||||
"net"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -39,3 +43,21 @@ func TestPing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMac(t *testing.T) {
|
||||
interfaces, _ := net.Interfaces()
|
||||
hostInterface, _ := net2.ChooseHostInterface()
|
||||
for _, i := range interfaces {
|
||||
//fmt.Printf("%s -> %s\n", i.Name, i.HardwareAddr.String())
|
||||
addrs, _ := i.Addrs()
|
||||
for _, addr := range addrs {
|
||||
if hostInterface.Equal(addr.(*net.IPNet).IP) {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(i.HardwareAddr.String()))
|
||||
sum := hash.Sum(nil)
|
||||
toInt := remote.BytesToInt(sum)
|
||||
fmt.Println(toInt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@@ -9,12 +12,14 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
net2 "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -22,12 +27,12 @@ import (
|
||||
|
||||
var stopChan = make(chan os.Signal)
|
||||
|
||||
func addCleanUpResourceHandler(client *kubernetes.Clientset, namespace string, ip *net.IPNet) {
|
||||
signal.Notify(stopChan, os.Interrupt, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL /*, syscall.SIGSTOP*/)
|
||||
func AddCleanUpResourceHandler(client *kubernetes.Clientset, namespace string, ip *net.IPNet) {
|
||||
signal.Notify(stopChan, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL /*, syscall.SIGSTOP*/)
|
||||
go func() {
|
||||
<-stopChan
|
||||
log.Info("prepare to exit, cleaning up")
|
||||
cleanUpTrafficManagerIfRefCountIsZero(client, namespace)
|
||||
//cleanUpTrafficManagerIfRefCountIsZero(client, namespace)
|
||||
err := ReleaseIpToDHCP(client, namespace, ip)
|
||||
if err != nil {
|
||||
log.Errorf("failed to release ip to dhcp, err: %v", err)
|
||||
@@ -162,21 +167,88 @@ func GetIpFromDHCP(client *kubernetes.Clientset, namespace string) (*net.IPNet,
|
||||
return nil, err
|
||||
}
|
||||
split := strings.Split(get.Data["DHCP"], ",")
|
||||
ip := split[0]
|
||||
split = split[1:]
|
||||
get.Data["DHCP"] = strings.Join(split, ",")
|
||||
|
||||
ip, left := getIp(split)
|
||||
|
||||
get.Data["DHCP"] = strings.Join(left, ",")
|
||||
_, err = client.CoreV1().ConfigMaps(namespace).Update(context.Background(), get, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("update dhcp error after get ip, need to put ip back, err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
atoi, _ := strconv.Atoi(ip)
|
||||
|
||||
return &net.IPNet{
|
||||
IP: net.IPv4(192, 168, 254, byte(atoi)),
|
||||
IP: net.IPv4(192, 168, 254, byte(ip)),
|
||||
Mask: net.IPv4Mask(255, 255, 255, 0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getIp(availableIp []string) (int, []string) {
|
||||
var v uint32
|
||||
interfaces, _ := net.Interfaces()
|
||||
hostInterface, _ := net2.ChooseHostInterface()
|
||||
out:
|
||||
for _, i := range interfaces {
|
||||
addrs, _ := i.Addrs()
|
||||
for _, addr := range addrs {
|
||||
if hostInterface.Equal(addr.(*net.IPNet).IP) {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(i.HardwareAddr.String()))
|
||||
sum := hash.Sum(nil)
|
||||
v = BytesToInt(sum)
|
||||
break out
|
||||
}
|
||||
}
|
||||
}
|
||||
m := make(map[int]int)
|
||||
for _, s := range availableIp {
|
||||
atoi, _ := strconv.Atoi(s)
|
||||
m[atoi] = atoi
|
||||
}
|
||||
for {
|
||||
if k, ok := m[int(v%256)]; ok {
|
||||
delete(m, k)
|
||||
return k, getValueFromMap(m)
|
||||
} else {
|
||||
v++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getValueFromMap(m map[int]int) []string {
|
||||
var result []int
|
||||
for _, v := range m {
|
||||
result = append(result, v)
|
||||
}
|
||||
sort.Ints(result)
|
||||
var s []string
|
||||
for _, i := range result {
|
||||
s = append(s, strconv.Itoa(i))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func sortString(m []string) []string {
|
||||
var result []int
|
||||
for _, v := range m {
|
||||
atoi, _ := strconv.Atoi(v)
|
||||
result = append(result, atoi)
|
||||
}
|
||||
sort.Ints(result)
|
||||
var s []string
|
||||
for _, i := range result {
|
||||
s = append(s, strconv.Itoa(i))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func BytesToInt(b []byte) uint32 {
|
||||
buffer := bytes.NewBuffer(b)
|
||||
var u uint32
|
||||
binary.Read(buffer, binary.BigEndian, &u)
|
||||
return u
|
||||
}
|
||||
|
||||
func ReleaseIpToDHCP(client *kubernetes.Clientset, namespace string, ip *net.IPNet) error {
|
||||
get, err := client.CoreV1().ConfigMaps(namespace).Get(context.Background(), TrafficManager, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
@@ -185,7 +257,7 @@ func ReleaseIpToDHCP(client *kubernetes.Clientset, namespace string, ip *net.IPN
|
||||
}
|
||||
split := strings.Split(get.Data["DHCP"], ",")
|
||||
split = append(split, strings.Split(ip.IP.To4().String(), ".")[3])
|
||||
get.Data["DHCP"] = strings.Join(split, ",")
|
||||
get.Data["DHCP"] = strings.Join(sortString(split), ",")
|
||||
_, err = client.CoreV1().ConfigMaps(namespace).Update(context.Background(), get, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("update dhcp error after release ip, need to try again, err: %v", err)
|
||||
|
||||
@@ -2,7 +2,8 @@ package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/sirupsen/logrus"
|
||||
"errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -10,14 +11,13 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubectl/pkg/polymorphichelpers"
|
||||
"k8s.io/kubectl/pkg/util/podutils"
|
||||
"log"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
const TrafficManager = "kubevpn.traffic.manager"
|
||||
|
||||
func CreateServer(clientset *kubernetes.Clientset, namespace, ip string) string {
|
||||
func CreateServer(clientset *kubernetes.Clientset, namespace, ip string) error {
|
||||
firstPod, i, err3 := polymorphichelpers.GetFirstPod(clientset.CoreV1(),
|
||||
namespace,
|
||||
fields.OneTermEqualSelector("app", TrafficManager).String(),
|
||||
@@ -28,7 +28,7 @@ func CreateServer(clientset *kubernetes.Clientset, namespace, ip string) string
|
||||
)
|
||||
|
||||
if err3 == nil && i != 0 && firstPod != nil {
|
||||
return firstPod.GetName()
|
||||
return nil
|
||||
}
|
||||
|
||||
t := true
|
||||
@@ -100,8 +100,9 @@ out:
|
||||
}
|
||||
case <-tick:
|
||||
watch.Stop()
|
||||
logrus.Error("timeout")
|
||||
log.Error("timeout")
|
||||
return errors.New("timeout")
|
||||
}
|
||||
}
|
||||
return name
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,14 +62,16 @@ func TestGetIPFromDHCP(t *testing.T) {
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
ipNet, err := GetIpFromDHCP(clientset, "test")
|
||||
ipNet2, err := GetIpFromDHCP(clientset, "test")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
} else {
|
||||
fmt.Println(ipNet.String())
|
||||
fmt.Printf("%s->%s\n", ipNet.String(), ipNet2.String())
|
||||
}
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
err = ReleaseIpToDHCP(clientset, "test", ipNet)
|
||||
err = ReleaseIpToDHCP(clientset, "test", ipNet2)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user