diff --git a/server/base/cfg.go b/server/base/cfg.go index c340b37..d6f27be 100644 --- a/server/base/cfg.go +++ b/server/base/cfg.go @@ -8,8 +8,10 @@ import ( ) const ( - LinkModeTUN = "tun" - LinkModeTAP = "tap" + LinkModeTUN = "tun" + LinkModeTAP = "tap" + LinkModeMacvtap = "macvtap" + LinkModeIpvtap = "ipvtap" ) var ( @@ -48,11 +50,12 @@ type ServerConfig struct { AdminPass string `json:"admin_pass"` JwtSecret string `json:"jwt_secret"` - LinkMode string `json:"link_mode"` // tun tap - Ipv4CIDR string `json:"ipv4_cidr"` // 192.168.1.0/24 - Ipv4Gateway string `json:"ipv4_gateway"` - Ipv4Start string `json:"ipv4_start"` // 192.168.1.100 - Ipv4End string `json:"ipv4_end"` // 192.168.1.200 + LinkMode string `json:"link_mode"` // tun tap macvtap ipvtap + Ipv4Master string `json:"ipv4_master"` // eth0 + Ipv4CIDR string `json:"ipv4_cidr"` // 192.168.10.0/24 + Ipv4Gateway string `json:"ipv4_gateway"` // 192.168.10.1 + Ipv4Start string `json:"ipv4_start"` // 192.168.10.100 + Ipv4End string `json:"ipv4_end"` // 192.168.10.200 IpLease int `json:"ip_lease"` MaxClient int `json:"max_client"` diff --git a/server/base/config.go b/server/base/config.go index 954f796..1bcc09b 100644 --- a/server/base/config.go +++ b/server/base/config.go @@ -26,19 +26,20 @@ var configs = []config{ {Typ: cfgStr, Name: "server_dtls_addr", Usage: "DTLS监听地址", ValStr: ":4433"}, {Typ: cfgStr, Name: "admin_addr", Usage: "后台服务监听地址", ValStr: ":8800"}, {Typ: cfgBool, Name: "proxy_protocol", Usage: "TCP代理协议", ValBool: false}, - {Typ: cfgStr, Name: "db_type", Usage: "数据库类型 [sqlite3、mysql、postgres]", ValStr: "sqlite3"}, + {Typ: cfgStr, Name: "db_type", Usage: "数据库类型 [sqlite3 mysql postgres]", ValStr: "sqlite3"}, {Typ: cfgStr, Name: "db_source", Usage: "数据库source", ValStr: "./conf/anylink.db"}, {Typ: cfgStr, Name: "cert_file", Usage: "证书文件", ValStr: "./conf/vpn_cert.pem"}, {Typ: cfgStr, Name: "cert_key", Usage: "证书密钥", ValStr: "./conf/vpn_cert.key"}, {Typ: cfgStr, Name: "files_path", Usage: "外部下载文件路径", ValStr: "./conf/files"}, {Typ: cfgStr, Name: "log_path", Usage: "日志文件路径,默认标准输出", ValStr: ""}, - {Typ: cfgStr, Name: "log_level", Usage: "日志等级 [debug、info、warn、error]", ValStr: "info"}, + {Typ: cfgStr, Name: "log_level", Usage: "日志等级 [debug info warn error]", ValStr: "info"}, {Typ: cfgBool, Name: "pprof", Usage: "开启pprof", ValBool: false}, {Typ: cfgStr, Name: "issuer", Usage: "系统名称", ValStr: "XX公司VPN"}, {Typ: cfgStr, Name: "admin_user", Usage: "管理用户名", ValStr: "admin"}, {Typ: cfgStr, Name: "admin_pass", Usage: "管理用户密码", ValStr: defaultPwd}, {Typ: cfgStr, Name: "jwt_secret", Usage: "JWT密钥", ValStr: defaultJwt}, - {Typ: cfgStr, Name: "link_mode", Usage: "虚拟网络类型", ValStr: "tun"}, + {Typ: cfgStr, Name: "link_mode", Usage: "虚拟网络类型[tun tap macvtap ipvtap]", ValStr: "tun"}, + {Typ: cfgStr, Name: "ipv4_master", Usage: "ipv4主网卡名称", ValStr: "eth0"}, {Typ: cfgStr, Name: "ipv4_cidr", Usage: "ip地址网段", ValStr: "192.168.10.0/24"}, {Typ: cfgStr, Name: "ipv4_gateway", Usage: "ipv4_gateway", ValStr: "192.168.10.1"}, {Typ: cfgStr, Name: "ipv4_start", Usage: "IPV4开始地址", ValStr: "192.168.10.100"}, diff --git a/server/bridge-init.sh b/server/bridge-init.sh index 17a57ac..79aad07 100644 --- a/server/bridge-init.sh +++ b/server/bridge-init.sh @@ -1,18 +1,11 @@ #!/bin/bash -################################# -# Set up Ethernet bridge on Linux -# Requires: bridge-utils -################################# - #yum install bridge-utils # Define Bridge Interface br="anylink0" -# Define physical ethernet interface to be bridged -# with TAP interface(s) above. - +# 请根据sever服务器信息,更新下面的信息 eth="eth0" eth_ip="192.168.10.4/24" eth_broadcast="192.168.10.255" @@ -24,10 +17,10 @@ brctl addif $br $eth ip addr del $eth_ip dev $eth ip addr add 0.0.0.0 dev $eth -ip link set dev $eth ip promisc on +ip link set dev $eth up promisc on mac=`cat /sys/class/net/$eth/address` -ip link set up address $mac dev $br +ip link set dev $br up address $mac promisc on ip addr add $eth_ip broadcast $eth_broadcast dev $br diff --git a/server/conf/server-sample.toml b/server/conf/server-sample.toml index a97ffaa..3be1a12 100644 --- a/server/conf/server-sample.toml +++ b/server/conf/server-sample.toml @@ -38,6 +38,7 @@ proxy_protocol = false link_mode = "tun" #客户端分配的ip地址池 +ipv4_master = "eth0" ipv4_cidr = "192.168.10.0/24" ipv4_gateway = "192.168.10.1" ipv4_start = "192.168.10.100" diff --git a/server/go.mod b/server/go.mod index abb928f..6fe9484 100644 --- a/server/go.mod +++ b/server/go.mod @@ -26,6 +26,7 @@ require ( github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 + golang.org/x/sys v0.0.0-20210423082822-04245dca01da golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect xorm.io/xorm v1.1.2 diff --git a/server/handler/link_cstp.go b/server/handler/link_cstp.go index bd7cf70..b51540f 100644 --- a/server/handler/link_cstp.go +++ b/server/handler/link_cstp.go @@ -7,6 +7,7 @@ import ( "time" "github.com/bjdgyc/anylink/base" + "github.com/bjdgyc/anylink/pkg/utils" "github.com/bjdgyc/anylink/sessdata" ) @@ -29,7 +30,7 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio for { // 设置超时限制 - err = conn.SetReadDeadline(time.Now().Add(dead)) + err = conn.SetReadDeadline(utils.NowSec().Add(dead)) if err != nil { base.Error("SetDeadline: ", err) return diff --git a/server/handler/link_dtls.go b/server/handler/link_dtls.go index f45d951..e674ff2 100644 --- a/server/handler/link_dtls.go +++ b/server/handler/link_dtls.go @@ -5,6 +5,7 @@ import ( "time" "github.com/bjdgyc/anylink/base" + "github.com/bjdgyc/anylink/pkg/utils" "github.com/bjdgyc/anylink/sessdata" ) @@ -32,7 +33,7 @@ func LinkDtls(conn net.Conn, cSess *sessdata.ConnSession) { go dtlsWrite(conn, dSess, cSess) for { - err = conn.SetReadDeadline(time.Now().Add(dead)) + err = conn.SetReadDeadline(utils.NowSec().Add(dead)) if err != nil { base.Error("SetDeadline: ", err) return diff --git a/server/handler/link_tap.go b/server/handler/link_tap.go index 65fc1ab..2e3062b 100644 --- a/server/handler/link_tap.go +++ b/server/handler/link_tap.go @@ -2,6 +2,7 @@ package handler import ( "fmt" + "io" "net" "github.com/bjdgyc/anylink/base" @@ -17,18 +18,32 @@ import ( const bridgeName = "anylink0" var ( - bridgeIp net.IP - bridgeHw net.HardwareAddr + // 网关mac地址 + gatewayHw net.HardwareAddr ) -func checkTap() { - brFace, err := net.InterfaceByName(bridgeName) +type LinkDriver interface { + io.ReadWriteCloser + Name() string +} + +func _setGateway() { + dstAddr := arpdis.Lookup(sessdata.IpPool.Ipv4Gateway, false) + gatewayHw = dstAddr.HardwareAddr + // 设置为静态地址映射 + dstAddr.Type = arpdis.TypeStatic + arpdis.Add(dstAddr) +} + +func _checkTapIp(ifName string) { + iFace, err := net.InterfaceByName(ifName) if err != nil { base.Fatal("testTap err: ", err) } - bridgeHw = brFace.HardwareAddr - addrs, err := brFace.Addrs() + var ifIp net.IP + + addrs, err := iFace.Addrs() if err != nil { base.Fatal("testTap err: ", err) } @@ -37,17 +52,19 @@ func checkTap() { if err != nil || ip.To4() == nil { continue } - bridgeIp = ip - } - if bridgeIp == nil && bridgeHw == nil { - base.Fatal("bridgeIp is err") + ifIp = ip } - if !sessdata.IpPool.Ipv4IPNet.Contains(bridgeIp) { - base.Fatal("bridgeIp or Ip network err") + if !sessdata.IpPool.Ipv4IPNet.Contains(ifIp) { + base.Fatal("tapIp or Ip network err") } } +func checkTap() { + _setGateway() + _checkTapIp(bridgeName) +} + // 创建tap网卡 func LinkTap(cSess *sessdata.ConnSession) error { cfg := water.Config{ @@ -60,9 +77,8 @@ func LinkTap(cSess *sessdata.ConnSession) error { return err } - cSess.TunName = ifce.Name() + cSess.SetIfName(ifce.Name()) - // arp on cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast on", ifce.Name(), cSess.Mtu) cmdstr2 := fmt.Sprintf("ip link set dev %s master %s", ifce.Name(), bridgeName) err = execCmd([]string{cmdstr1, cmdstr2}) @@ -75,25 +91,31 @@ func LinkTap(cSess *sessdata.ConnSession) error { cmdstr3 := fmt.Sprintf("sysctl -w net.ipv6.conf.%s.disable_ipv6=1", ifce.Name()) execCmd([]string{cmdstr3}) - go tapRead(ifce, cSess) - go tapWrite(ifce, cSess) + go allTapRead(ifce, cSess) + go allTapWrite(ifce, cSess) return nil } -func tapWrite(ifce *water.Interface, cSess *sessdata.ConnSession) { +// ========================通用代码=========================== + +func allTapWrite(ifce LinkDriver, cSess *sessdata.ConnSession) { defer func() { base.Debug("LinkTap return", cSess.IpAddr) cSess.Close() - _ = ifce.Close() + ifce.Close() }() var ( err error + dstHw net.HardwareAddr pl *sessdata.Payload - frame ethernet.Frame + frame = make(ethernet.Frame, BufferSize) + ipDst = net.IPv4(1, 2, 3, 4) ) for { + frame.Resize(BufferSize) + select { case pl = <-cSess.PayloadIn: case <-cSess.CloseChan: @@ -101,45 +123,46 @@ func tapWrite(ifce *water.Interface, cSess *sessdata.ConnSession) { } // var frame ethernet.Frame - fb := getByteFull() - frame = *fb switch pl.LType { default: // log.Println(payload) case sessdata.LTypeEthernet: copy(frame, pl.Data) frame = frame[:len(pl.Data)] + + // packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.Default) + // fmt.Println("wirteArp:", packet) case sessdata.LTypeIPData: // 需要转换成 Ethernet 数据 - ip_src := waterutil.IPv4Source(pl.Data) - if waterutil.IsIPv6(pl.Data) || !ip_src.Equal(cSess.IpAddr) { - // 过滤掉IPv6的数据 + ipSrc := waterutil.IPv4Source(pl.Data) + if !ipSrc.Equal(cSess.IpAddr) { // 非分配给客户端ip,直接丢弃 continue } - // packet := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.Default) + if waterutil.IsIPv6(pl.Data) { + // 过滤掉IPv6的数据 + continue + } + + // packet := gopacket.NewPacket(pl.Data, layers.LayerTypeIPv4, gopacket.Default) // fmt.Println("get:", packet) - ip_dst := waterutil.IPv4Destination(pl.Data) - // fmt.Println("get:", ip_src, ip_dst) + // 手动设置ipv4地址 + ipDst[12] = pl.Data[16] + ipDst[13] = pl.Data[17] + ipDst[14] = pl.Data[18] + ipDst[15] = pl.Data[19] - var dstHw net.HardwareAddr - if !sessdata.IpPool.Ipv4IPNet.Contains(ip_dst) || ip_dst.Equal(sessdata.IpPool.Ipv4Gateway) { - // 不是同一网段,使用网关mac地址 - dstAddr := arpdis.Lookup(sessdata.IpPool.Ipv4Gateway, false) - dstHw = dstAddr.HardwareAddr - } else { - dstAddr := arpdis.Lookup(ip_dst, true) + dstHw = gatewayHw + if sessdata.IpPool.Ipv4IPNet.Contains(ipDst) { + dstAddr := arpdis.Lookup(ipDst, true) // fmt.Println("dstAddr", dstAddr) if dstAddr != nil { dstHw = dstAddr.HardwareAddr - } else { - dstHw = bridgeHw } - } - // fmt.Println("Gateway", ip_dst, dstAddr.HardwareAddr) + // fmt.Println("Gateway", ipSrc, ipDst, dstHw) frame.Prepare(dstHw, cSess.MacHw, ethernet.NotTagged, ethernet.IPv4, len(pl.Data)) copy(frame[12+2:], pl.Data) } @@ -152,29 +175,26 @@ func tapWrite(ifce *water.Interface, cSess *sessdata.ConnSession) { return } - putByte(fb) putPayload(pl) } } -func tapRead(ifce *water.Interface, cSess *sessdata.ConnSession) { +func allTapRead(ifce LinkDriver, cSess *sessdata.ConnSession) { defer func() { base.Debug("tapRead return", cSess.IpAddr) - _ = ifce.Close() + ifce.Close() }() var ( err error n int data []byte - frame ethernet.Frame + frame = make(ethernet.Frame, BufferSize) ) for { - // var frame ethernet.Frame - // frame.Resize(BufferSize) - fb := getByteFull() - frame = *fb + frame.Resize(BufferSize) + n, err = ifce.Read(frame) if err != nil { base.Error("tap Read err", n, err) @@ -184,8 +204,6 @@ func tapRead(ifce *water.Interface, cSess *sessdata.ConnSession) { switch frame.Ethertype() { default: - // packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.Default) - // fmt.Println(packet) continue case ethernet.IPv6: continue @@ -214,7 +232,7 @@ func tapRead(ifce *water.Interface, cSess *sessdata.ConnSession) { case ethernet.ARP: // 暂时仅实现了ARP协议 - packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.Default) + packet := gopacket.NewPacket(frame, layers.LayerTypeEthernet, gopacket.NoCopy) layer := packet.Layer(layers.LayerTypeARP) arpReq := layer.(*layers.ARP) @@ -223,12 +241,12 @@ func tapRead(ifce *water.Interface, cSess *sessdata.ConnSession) { continue } - // fmt.Println("arp", net.IP(arpReq.SourceProtAddress), sess.Ip) + // fmt.Println("arp", time.Now(), net.IP(arpReq.SourceProtAddress), cSess.IpAddr) // fmt.Println(packet) // 返回ARP数据 src := &arpdis.Addr{IP: cSess.IpAddr, HardwareAddr: cSess.MacHw} - dst := &arpdis.Addr{IP: arpReq.SourceProtAddress, HardwareAddr: frame.Source()} + dst := &arpdis.Addr{IP: arpReq.SourceProtAddress, HardwareAddr: arpReq.SourceHwAddress} data, err = arpdis.NewARPReply(src, dst) if err != nil { base.Error(err) @@ -237,13 +255,9 @@ func tapRead(ifce *water.Interface, cSess *sessdata.ConnSession) { // 从接受的arp信息添加arp地址 addr := &arpdis.Addr{ - IP: make([]byte, len(arpReq.SourceProtAddress)), - HardwareAddr: make([]byte, len(frame.Source())), + IP: append([]byte{}, dst.IP...), + HardwareAddr: append([]byte{}, dst.HardwareAddr...), } - // addr.IP = arpReq.SourceProtAddress - // addr.HardwareAddr = frame.Source() - copy(addr.IP, arpReq.SourceProtAddress) - copy(addr.HardwareAddr, frame.Source()) arpdis.Add(addr) pl := getPayload() @@ -259,7 +273,5 @@ func tapRead(ifce *water.Interface, cSess *sessdata.ConnSession) { } } - - putByte(fb) } } diff --git a/server/handler/link_tun.go b/server/handler/link_tun.go index a8df140..2f0045c 100644 --- a/server/handler/link_tun.go +++ b/server/handler/link_tun.go @@ -40,8 +40,7 @@ func LinkTun(cSess *sessdata.ConnSession) error { return err } // log.Printf("Interface Name: %s\n", ifce.Name()) - cSess.SetTunName(ifce.Name()) - // cSess.TunName = ifce.Name() + cSess.SetIfName(ifce.Name()) cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast off", ifce.Name(), cSess.Mtu) cmdstr2 := fmt.Sprintf("ip addr add dev %s local %s peer %s/32", diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index e04dd04..e2eeb2e 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -160,9 +160,12 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { err = LinkTun(cSess) case base.LinkModeTAP: err = LinkTap(cSess) + case base.LinkModeMacvtap: + err = LinkMacvtap(cSess) } if err != nil { - w.WriteHeader(http.StatusInternalServerError) + conn.Close() + base.Error(err) return } diff --git a/server/handler/link_vtap.go b/server/handler/link_vtap.go new file mode 100644 index 0000000..3ab5619 --- /dev/null +++ b/server/handler/link_vtap.go @@ -0,0 +1,137 @@ +package handler + +import ( + "fmt" + "net" + "os" + "strings" + "syscall" + "unsafe" + + "github.com/bjdgyc/anylink/base" + "github.com/bjdgyc/anylink/pkg/utils" + "github.com/bjdgyc/anylink/sessdata" +) + +// link vtap +const vTapPrefix = "lvtap" + +type Vtap struct { + *os.File + ifName string +} + +func (v *Vtap) Close() error { + v.File.Close() + cmdstr := fmt.Sprintf("ip link del %s", v.ifName) + return execCmd([]string{cmdstr}) +} + +func checkMacvtap() { + _setGateway() + _checkTapIp(base.Cfg.Ipv4Master) + + ifName := "anylinkMacvtap" + // 加载 macvtap + cmdstr0 := fmt.Sprintf("modprobe -i macvtap") + // 开启主网卡混杂模式 + cmdstr1 := fmt.Sprintf("ip link set dev %s promisc on", base.Cfg.Ipv4Master) + // 测试 macvtap 功能 + cmdstr2 := fmt.Sprintf("ip link add link %s name %s type macvtap mode bridge", base.Cfg.Ipv4Master, ifName) + cmdstr3 := fmt.Sprintf("ip link del %s", ifName) + err := execCmd([]string{cmdstr0, cmdstr1, cmdstr2, cmdstr3}) + if err != nil { + base.Fatal(err) + } +} + +// 创建 Macvtap 网卡 +func LinkMacvtap(cSess *sessdata.ConnSession) error { + capL := sessdata.IpPool.IpLongMax - sessdata.IpPool.IpLongMin + ipN := utils.Ip2long(cSess.IpAddr) % capL + ifName := fmt.Sprintf("%s%d", vTapPrefix, ipN) + + cSess.SetIfName(ifName) + + cmdstr1 := fmt.Sprintf("ip link add link %s name %s type macvtap mode bridge", base.Cfg.Ipv4Master, ifName) + cmdstr2 := fmt.Sprintf("ip link set dev %s up mtu %d address %s", ifName, cSess.Mtu, cSess.MacHw) + err := execCmd([]string{cmdstr1, cmdstr2}) + if err != nil { + base.Error(err) + return err + } + cmdstr3 := fmt.Sprintf("sysctl -w net.ipv6.conf.%s.disable_ipv6=1", ifName) + execCmd([]string{cmdstr3}) + + return createVtap(cSess, ifName) +} + +func checkIpvtap() { + +} + +// 创建 Ipvtap 网卡 +func LinkIpvtap(cSess *sessdata.ConnSession) error { + return nil +} + +type ifReq struct { + Name [0x10]byte + Flags uint16 + pad [0x28 - 0x10 - 2]byte +} + +func createVtap(cSess *sessdata.ConnSession, ifName string) error { + // 初始化 ifName + inf, err := net.InterfaceByName(ifName) + if err != nil { + base.Error(err) + return err + } + + tName := fmt.Sprintf("/dev/tap%d", inf.Index) + + var fdInt int + + fdInt, err = syscall.Open(tName, os.O_RDWR|syscall.O_NONBLOCK, 0) + if err != nil { + return err + } + + var flags uint16 = syscall.IFF_TAP | syscall.IFF_NO_PI + var req ifReq + req.Flags = flags + + _, _, errno := syscall.Syscall( + syscall.SYS_IOCTL, + uintptr(fdInt), + uintptr(syscall.TUNSETIFF), + uintptr(unsafe.Pointer(&req)), + ) + if errno != 0 { + return os.NewSyscallError("ioctl", errno) + } + + file := os.NewFile(uintptr(fdInt), tName) + ifce := &Vtap{file, ifName} + + go allTapRead(ifce, cSess) + go allTapWrite(ifce, cSess) + return nil +} + +// 销毁未关闭的vtap +func destroyVtap() { + its, err := net.Interfaces() + if err != nil { + base.Error(err) + return + } + for _, v := range its { + if strings.HasPrefix(v.Name, vTapPrefix) { + // 删除原来的网卡 + cmdstr := fmt.Sprintf("ip link del %s", v.Name) + execCmd([]string{cmdstr}) + } + } +} diff --git a/server/handler/start.go b/server/handler/start.go index d074244..5399bec 100644 --- a/server/handler/start.go +++ b/server/handler/start.go @@ -11,10 +11,17 @@ func Start() { dbdata.Start() sessdata.Start() - checkTun() - if base.Cfg.LinkMode == base.LinkModeTAP { + switch base.Cfg.LinkMode { + case base.LinkModeTUN: + checkTun() + case base.LinkModeTAP: checkTap() + case base.LinkModeMacvtap: + checkMacvtap() + default: + base.Fatal("LinkMode is err") } + go admin.StartAdmin() go startTls() go startDtls() @@ -22,4 +29,5 @@ func Start() { func Stop() { _ = dbdata.Stop() + destroyVtap() } diff --git a/server/main.go b/server/main.go index f2efc9e..c52ddcf 100644 --- a/server/main.go +++ b/server/main.go @@ -11,7 +11,6 @@ import ( "syscall" "github.com/bjdgyc/anylink/admin" - "github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/handler" ) diff --git a/server/pkg/arpdis/addr.go b/server/pkg/arpdis/addr.go index fb46bad..12be814 100644 --- a/server/pkg/arpdis/addr.go +++ b/server/pkg/arpdis/addr.go @@ -4,6 +4,8 @@ import ( "net" "sync" "time" + + "github.com/bjdgyc/anylink/pkg/utils" ) const ( @@ -16,7 +18,7 @@ const ( ) var ( - table = make(map[string]*Addr) + table = make(map[string]*Addr, 128) tableMu sync.RWMutex ) @@ -40,25 +42,25 @@ func Lookup(ip net.IP, onlyTable bool) *Addr { // Add adds a IP-MAC map to a runtime ARP table. func tableLookup(ip net.IP) *Addr { - tableMu.Lock() + tableMu.RLock() addr := table[ip.To4().String()] - tableMu.Unlock() + tableMu.RUnlock() if addr == nil { return nil } // 判断老化过期时间 - tsub := time.Since(addr.disTime) + tSub := utils.NowSec().Sub(addr.disTime) switch addr.Type { + case TypeStatic: case TypeNormal: - if tsub > StaleTimeNormal { + if tSub > StaleTimeNormal { return nil } case TypeUnreachable: - if tsub > StaleTimeUnreachable { + if tSub > StaleTimeUnreachable { return nil } - case TypeStatic: } return addr @@ -70,7 +72,7 @@ func Add(addr *Addr) { return } if addr.disTime.IsZero() { - addr.disTime = time.Now() + addr.disTime = utils.NowSec() } ip := addr.IP.To4().String() tableMu.Lock() diff --git a/server/pkg/arpdis/lookup.go b/server/pkg/arpdis/lookup.go index f5457be..146507c 100644 --- a/server/pkg/arpdis/lookup.go +++ b/server/pkg/arpdis/lookup.go @@ -19,7 +19,8 @@ func doLookup(ip net.IP) *Addr { err := doPing(ip.String()) if err != nil { // log.Println(err) - addr := &Addr{IP: ip, Type: TypeUnreachable} + addr := &Addr{IP: net.IPv4(1, 2, 3, 4), Type: TypeUnreachable} + copy(addr.IP, ip) return addr } @@ -50,7 +51,9 @@ func doArpShow(ip net.IP) *Addr { return nil } - return &Addr{IP: ip, HardwareAddr: mac} + addr := &Addr{IP: net.IPv4(1, 2, 3, 4), HardwareAddr: mac} + copy(addr.IP, ip) + return addr } // IP address HW type Flags HW address Mask Device diff --git a/server/pkg/utils/ip.go b/server/pkg/utils/ip.go new file mode 100644 index 0000000..cb822ec --- /dev/null +++ b/server/pkg/utils/ip.go @@ -0,0 +1,17 @@ +package utils + +import ( + "encoding/binary" + "net" +) + +func Long2ip(i uint32) net.IP { + ip := make([]byte, 4) + binary.BigEndian.PutUint32(ip, i) + return ip +} + +func Ip2long(ip net.IP) uint32 { + ip = ip.To4() + return binary.BigEndian.Uint32(ip) +} diff --git a/server/sessdata/ip_pool.go b/server/sessdata/ip_pool.go index add931d..7fdf207 100644 --- a/server/sessdata/ip_pool.go +++ b/server/sessdata/ip_pool.go @@ -1,13 +1,13 @@ package sessdata import ( - "encoding/binary" "net" "sync" "time" "github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/dbdata" + "github.com/bjdgyc/anylink/pkg/utils" ) var ( @@ -43,19 +43,8 @@ func initIpPool() { // max := min | uint32(math.Pow(2, float64(32-one))-1) // ip地址池 - IpPool.IpLongMin = ip2long(net.ParseIP(base.Cfg.Ipv4Start)) - IpPool.IpLongMax = ip2long(net.ParseIP(base.Cfg.Ipv4End)) -} - -func long2ip(i uint32) net.IP { - ip := make([]byte, 4) - binary.BigEndian.PutUint32(ip, i) - return ip -} - -func ip2long(ip net.IP) uint32 { - ip = ip.To4() - return binary.BigEndian.Uint32(ip) + IpPool.IpLongMin = utils.Ip2long(net.ParseIP(base.Cfg.Ipv4Start)) + IpPool.IpLongMax = utils.Ip2long(net.ParseIP(base.Cfg.Ipv4End)) } // AcquireIp 获取动态ip @@ -90,7 +79,7 @@ func AcquireIp(username, macAddr string) net.IP { farIp := &dbdata.IpMap{LastLogin: tNow} // 全局遍历超过租期ip for i := IpPool.IpLongMin; i <= IpPool.IpLongMax; i++ { - ip := long2ip(i) + ip := utils.Long2ip(i) ipStr := ip.String() // 跳过活跃连接 diff --git a/server/sessdata/online.go b/server/sessdata/online.go index df1cee8..ca97aa7 100644 --- a/server/sessdata/online.go +++ b/server/sessdata/online.go @@ -54,13 +54,13 @@ func OnlineSess() []Online { Group: v.Group, MacAddr: v.MacAddr, RemoteAddr: v.CSess.RemoteAddr, - TunName: v.CSess.TunName, + TunName: v.CSess.IfName, Mtu: v.CSess.Mtu, Client: v.CSess.Client, BandwidthUp: utils.HumanByte(atomic.LoadUint32(&v.CSess.BandwidthUpPeriod)) + "/s", BandwidthDown: utils.HumanByte(atomic.LoadUint32(&v.CSess.BandwidthDownPeriod)) + "/s", - BandwidthUpAll: utils.HumanByte(atomic.LoadUint32(&v.CSess.BandwidthUpAll)), - BandwidthDownAll: utils.HumanByte(atomic.LoadUint32(&v.CSess.BandwidthDownAll)), + BandwidthUpAll: utils.HumanByte(atomic.LoadUint64(&v.CSess.BandwidthUpAll)), + BandwidthDownAll: utils.HumanByte(atomic.LoadUint64(&v.CSess.BandwidthDownAll)), LastLogin: v.LastLogin, } datas = append(datas, val) diff --git a/server/sessdata/session.go b/server/sessdata/session.go index 9b9d2dc..764b08c 100644 --- a/server/sessdata/session.go +++ b/server/sessdata/session.go @@ -32,7 +32,7 @@ type ConnSession struct { MacHw net.HardwareAddr // 客户端mac地址,从Session取出 RemoteAddr string Mtu int - TunName string + IfName string Client string // 客户端 mobile pc CstpDpd int Group *dbdata.Group @@ -41,8 +41,8 @@ type ConnSession struct { BandwidthDown uint32 // 使用下行带宽 Byte BandwidthUpPeriod uint32 // 前一周期的总量 BandwidthDownPeriod uint32 - BandwidthUpAll uint32 // 使用上行带宽总量 - BandwidthDownAll uint32 // 使用下行带宽总量 + BandwidthUpAll uint64 // 使用上行带宽总量 + BandwidthDownAll uint64 // 使用下行带宽总量 closeOnce sync.Once CloseChan chan struct{} PayloadIn chan *Payload @@ -111,9 +111,9 @@ func checkSession() { func GenToken() string { // 生成32位的 token - btoken := make([]byte, 32) - rand.Read(btoken) - return fmt.Sprintf("%x", btoken) + bToken := make([]byte, 32) + rand.Read(bToken) + return fmt.Sprintf("%x", bToken) } func NewSession(token string) *Session { @@ -285,8 +285,8 @@ func (cs *ConnSession) ratePeriod() { atomic.SwapUint32(&cs.BandwidthUpPeriod, rtUp/BandwidthPeriodSec) atomic.SwapUint32(&cs.BandwidthDownPeriod, rtDown/BandwidthPeriodSec) // 累加所有流量 - atomic.AddUint32(&cs.BandwidthUpAll, rtUp) - atomic.AddUint32(&cs.BandwidthDownAll, rtDown) + atomic.AddUint64(&cs.BandwidthUpAll, uint64(rtUp)) + atomic.AddUint64(&cs.BandwidthDownAll, uint64(rtDown)) } } @@ -305,10 +305,10 @@ func (cs *ConnSession) SetMtu(mtu string) { } } -func (cs *ConnSession) SetTunName(name string) { +func (cs *ConnSession) SetIfName(name string) { cs.Sess.mux.Lock() defer cs.Sess.mux.Unlock() - cs.TunName = name + cs.IfName = name } func (cs *ConnSession) RateLimit(byt int, isUp bool) error {