From 000b04157879cc04b3d8478ac032ad2f738bbb20 Mon Sep 17 00:00:00 2001
From: bjdgyc <bjdgyc@163.com>
Date: Thu, 14 Mar 2024 16:47:25 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20atomic=20=E5=BC=95?=
 =?UTF-8?q?=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                   | 17 ++++++++++++++---
 server/base/mod.go          |  9 ++++-----
 server/go.mod               |  2 +-
 server/handler/link_base.go |  5 +++--
 server/handler/link_cstp.go |  8 ++++----
 server/handler/link_dtls.go |  2 +-
 server/handler/link_tun.go  | 18 ++++++++++--------
 server/handler/link_vtap.go |  9 +++++----
 server/pkg/utils/util.go    |  9 +++++++++
 server/sessdata/session.go  | 17 ++++++++---------
 10 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/README.md b/README.md
index 2db83a9..7e7230c 100644
--- a/README.md
+++ b/README.md
@@ -47,8 +47,10 @@ AnyLink 服务端仅在 CentOS 7、CentOS 8、Ubuntu 18.04、Ubuntu 20.04 测试
 > 没有编程基础的同学建议直接下载 release 包,从下面的地址下载 anylink-deploy.tar.gz
 >
 > https://github.com/bjdgyc/anylink/releases
+> 
+> https://gitee.com/bjdgyc/anylink/releases
 >
-> 如果不会安装,可以提供有偿远程协助服务(100 CNY)。添加QQ(68492170)联系我
+> 如果不会安装,可以提供有偿远程协助服务(200 CNY)。添加QQ(68492170)联系我
 > 
 > 也可以添加QQ群 咨询群内大佬,群共享文件有相关软件下载
 > 
@@ -58,11 +60,15 @@ AnyLink 服务端仅在 CentOS 7、CentOS 8、Ubuntu 18.04、Ubuntu 20.04 测试
 
 ### 使用问题
 
-> 对于测试环境,可以使用 vpn.test.vqilu.cn (已经备案) 绑定host进行测试
+> 对于测试环境,可以使用 vpn.test.vqilu.cn 绑定host进行测试
 >
 > 对于线上环境,必须申请安全的https证书(跟nginx使用的证书类型一致),不支持私有证书连接
 >
-> 服务端安装 yum install iproute 或者 apt-get install iproute2
+> 服务端依赖安装:
+> 
+> centos: yum install iptables iproute
+> 
+> ubuntu: apt-get install iptables iproute2
 >
 > 客户端请使用群共享文件的版本,其他版本没有测试过,不保证使用正常
 >
@@ -234,6 +240,11 @@ https://cloud.tencent.com/document/product/216/62007
 1. 设置配置文件
 
 > macvtap 设置相对比较简单,只需要配置相应的参数即可。
+> 
+> 网络要求:需要网络支持 ARP 传输,可通过 ARP 宣告普通内网 IP。
+> 
+> 网络限制:云环境下不能使用,网卡mac加白环境不能使用,802.1x认证网络不能使用
+> 
 > 以下参数可以通过执行 `ip a` 查看
 
 ```
diff --git a/server/base/mod.go b/server/base/mod.go
index c87fcc1..481e576 100644
--- a/server/base/mod.go
+++ b/server/base/mod.go
@@ -58,10 +58,9 @@ func CheckModOrLoad(mod string) {
 			// 文件存在
 			return
 		}
-		err = fmt.Errorf("[error] Linux tunFile is null %s", tunPath)
-		log.Println(err)
-		return
-		// panic(err)
+		// err = fmt.Errorf("[error] Linux tunFile is null %s", tunPath)
+		// log.Println(err)
+		// return
 	}
 
 	if InContainer {
@@ -76,7 +75,7 @@ func CheckModOrLoad(mod string) {
 	cmd := exec.Command("sh", "-c", cmdstr)
 	b, err := cmd.CombinedOutput()
 	if err != nil {
-		log.Println(string(b))
+		log.Println(mod, string(b))
 		panic(err)
 	}
 }
diff --git a/server/go.mod b/server/go.mod
index 566a740..4dfc190 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -33,7 +33,6 @@ require (
 	github.com/xhit/go-simple-mail/v2 v2.16.0
 	github.com/xlzd/gotp v0.1.0
 	github.com/xuri/excelize/v2 v2.8.1
-	go.uber.org/atomic v1.11.0
 	golang.org/x/crypto v0.21.0
 	golang.org/x/net v0.22.0
 	golang.org/x/text v0.14.0
@@ -66,6 +65,7 @@ require (
 	github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.873 // indirect
 	github.com/toorop/go-dkim v0.0.0-20240103092955-90b7d1423f92 // indirect
 	github.com/yusufpapurcu/wmi v1.2.4 // indirect
+	go.uber.org/atomic v1.11.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
 	golang.org/x/mod v0.16.0 // indirect
diff --git a/server/handler/link_base.go b/server/handler/link_base.go
index 48e2258..c46da15 100644
--- a/server/handler/link_base.go
+++ b/server/handler/link_base.go
@@ -2,8 +2,9 @@ package handler
 
 import (
 	"encoding/xml"
-	"log"
 	"os/exec"
+
+	"github.com/bjdgyc/anylink/base"
 )
 
 const BufferSize = 2048
@@ -46,7 +47,7 @@ func execCmd(cmdStrs []string) error {
 		cmd := exec.Command("sh", "-c", cmdStr)
 		b, err := cmd.CombinedOutput()
 		if err != nil {
-			log.Println(string(b))
+			base.Error(cmdStr, string(b))
 			return err
 		}
 	}
diff --git a/server/handler/link_cstp.go b/server/handler/link_cstp.go
index dfd3ba2..29d4a7b 100644
--- a/server/handler/link_cstp.go
+++ b/server/handler/link_cstp.go
@@ -25,9 +25,9 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio
 		n         int
 		dataLen   uint16
 		dead      = time.Second * time.Duration(cSess.CstpDpd+5)
-		idle      = time.Second * time.Duration(base.Cfg.IdleTimeout)
+		idle      = int64(base.Cfg.IdleTimeout)
 		checkIdle = base.Cfg.IdleTimeout > 0
-		lastTime  time.Time
+		lastTime  int64
 	)
 
 	go cstpWrite(conn, bufRW, cSess)
@@ -61,7 +61,7 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio
 			// 判断超时时间
 			if checkIdle {
 				lastTime = cSess.LastDataTime.Load()
-				if lastTime.Before(utils.NowSec().Add(-idle)) {
+				if lastTime < (utils.NowSec().Unix() - idle) {
 					base.Warn("IdleTimeout", cSess.Username, cSess.IpAddr, conn.RemoteAddr(), "lastTime", lastTime)
 					sessdata.CloseSess(cSess.Sess.Token, dbdata.UserIdleTimeout)
 					return
@@ -113,7 +113,7 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio
 				return
 			}
 			// 只记录返回正确的数据时间
-			cSess.LastDataTime.Store(utils.NowSec())
+			cSess.LastDataTime.Store(utils.NowSec().Unix())
 		}
 	}
 }
diff --git a/server/handler/link_dtls.go b/server/handler/link_dtls.go
index a2059db..c87a8f0 100644
--- a/server/handler/link_dtls.go
+++ b/server/handler/link_dtls.go
@@ -96,7 +96,7 @@ func LinkDtls(conn net.Conn, cSess *sessdata.ConnSession) {
 				return
 			}
 			// 只记录返回正确的数据时间
-			cSess.LastDataTime.Store(utils.NowSec())
+			cSess.LastDataTime.Store(utils.NowSec().Unix())
 		}
 
 	}
diff --git a/server/handler/link_tun.go b/server/handler/link_tun.go
index 78c272c..b01074d 100644
--- a/server/handler/link_tun.go
+++ b/server/handler/link_tun.go
@@ -4,12 +4,16 @@ import (
 	"fmt"
 
 	"github.com/bjdgyc/anylink/base"
+	"github.com/bjdgyc/anylink/pkg/utils"
 	"github.com/bjdgyc/anylink/sessdata"
 	"github.com/coreos/go-iptables/iptables"
 	"github.com/songgao/water"
 )
 
 func checkTun() {
+	// 测试ip命令
+	base.CheckModOrLoad("tun")
+
 	// 测试tun
 	cfg := water.Config{
 		DeviceType: water.TUN,
@@ -21,16 +25,14 @@ func checkTun() {
 	}
 	defer ifce.Close()
 
-	// 测试ip命令
-	base.CheckModOrLoad("tun")
-
 	cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %s multicast off", ifce.Name(), "1399")
 	err = execCmd([]string{cmdstr1})
 	if err != nil {
 		base.Fatal("testTun err: ", err)
 	}
 	// 开启服务器转发
-	if err := execCmd([]string{"sysctl -w net.ipv4.ip_forward=1"}); err != nil {
+	err = execCmd([]string{"sysctl -w net.ipv4.ip_forward=1"})
+	if err != nil {
 		base.Fatal(err)
 	}
 	if base.Cfg.IptablesNat {
@@ -47,14 +49,14 @@ func checkTun() {
 
 		// 添加注释
 		natRule := []string{"-s", base.Cfg.Ipv4CIDR, "-o", base.Cfg.Ipv4Master, "-m", "comment",
-			"--comment", "anylink tun nat", "-j", "MASQUERADE"}
+			"--comment", "AnyLink", "-j", "MASQUERADE"}
 		err = ipt.InsertUnique("nat", "POSTROUTING", 1, natRule...)
 		if err != nil {
 			base.Error(err)
 		}
 
 		// 添加注释
-		forwardRule := []string{"-m", "comment", "--comment", "anylink forward filter", "-j", "ACCEPT"}
+		forwardRule := []string{"-m", "comment", "--comment", "AnyLink", "-j", "ACCEPT"}
 		err = ipt.InsertUnique("filter", "FORWARD", 1, forwardRule...)
 		if err != nil {
 			base.Error(err)
@@ -80,8 +82,8 @@ func LinkTun(cSess *sessdata.ConnSession) error {
 	cSess.SetIfName(ifce.Name())
 
 	// 通过 ip link show  查看 alias 信息
-
-	cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast off alias %s.%s", ifce.Name(), cSess.Mtu, cSess.Group.Name, cSess.Username)
+	alias := utils.ParseName(cSess.Group.Name + "." + cSess.Username)
+	cmdstr1 := fmt.Sprintf("ip link set dev %s up mtu %d multicast off alias %s", ifce.Name(), cSess.Mtu, alias)
 	cmdstr2 := fmt.Sprintf("ip addr add dev %s local %s peer %s/32",
 		ifce.Name(), base.Cfg.Ipv4Gateway, cSess.IpAddr)
 	err = execCmd([]string{cmdstr1, cmdstr2})
diff --git a/server/handler/link_vtap.go b/server/handler/link_vtap.go
index 1096642..1b61294 100644
--- a/server/handler/link_vtap.go
+++ b/server/handler/link_vtap.go
@@ -28,12 +28,13 @@ func (v *Vtap) Close() error {
 }
 
 func checkMacvtap() {
+	// 加载 macvtap
+	base.CheckModOrLoad("macvtap")
+
 	_setGateway()
 	_checkTapIp(base.Cfg.Ipv4Master)
 
 	ifName := "anylinkMacvtap"
-	// 加载 macvtap
-	base.CheckModOrLoad("macvtap")
 
 	// 开启主网卡混杂模式
 	cmdstr1 := fmt.Sprintf("ip link set dev %s promisc on", base.Cfg.Ipv4Master)
@@ -55,8 +56,8 @@ func LinkMacvtap(cSess *sessdata.ConnSession) error {
 	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 alias %s.%s", ifName, cSess.Mtu,
-		cSess.MacHw, cSess.Group.Name, cSess.Username)
+	alias := utils.ParseName(cSess.Group.Name + "." + cSess.Username)
+	cmdstr2 := fmt.Sprintf("ip link set dev %s up mtu %d address %s alias %s", ifName, cSess.Mtu, cSess.MacHw, alias)
 
 	err := execCmd([]string{cmdstr1, cmdstr2})
 	if err != nil {
diff --git a/server/pkg/utils/util.go b/server/pkg/utils/util.go
index 6ce13c4..2b17f26 100644
--- a/server/pkg/utils/util.go
+++ b/server/pkg/utils/util.go
@@ -3,6 +3,7 @@ package utils
 import (
 	"fmt"
 	"math/rand"
+	"strings"
 	"sync/atomic"
 	"time"
 )
@@ -91,3 +92,11 @@ func RandomRunes(length int) string {
 
 	return string(bytes)
 }
+
+func ParseName(name string) string {
+	name = strings.ReplaceAll(name, " ", "-")
+	name = strings.ReplaceAll(name, "'", "-")
+	name = strings.ReplaceAll(name, "\"", "-")
+	name = strings.ReplaceAll(name, ";", "-")
+	return name
+}
diff --git a/server/sessdata/session.go b/server/sessdata/session.go
index a4e6ecd..60fae1d 100644
--- a/server/sessdata/session.go
+++ b/server/sessdata/session.go
@@ -13,7 +13,6 @@ import (
 	"github.com/bjdgyc/anylink/base"
 	"github.com/bjdgyc/anylink/dbdata"
 	mapset "github.com/deckarep/golang-set"
-	atomic2 "go.uber.org/atomic"
 )
 
 var (
@@ -41,15 +40,15 @@ type ConnSession struct {
 	CstpDpd             int
 	Group               *dbdata.Group
 	Limit               *LimitRater
-	BandwidthUp         atomic2.Uint32 // 使用上行带宽 Byte
-	BandwidthDown       atomic2.Uint32 // 使用下行带宽 Byte
-	BandwidthUpPeriod   atomic2.Uint32 // 前一周期的总量
-	BandwidthDownPeriod atomic2.Uint32
-	BandwidthUpAll      atomic2.Uint64 // 使用上行带宽总量
-	BandwidthDownAll    atomic2.Uint64 // 使用下行带宽总量
+	BandwidthUp         atomic.Uint32 // 使用上行带宽 Byte
+	BandwidthDown       atomic.Uint32 // 使用下行带宽 Byte
+	BandwidthUpPeriod   atomic.Uint32 // 前一周期的总量
+	BandwidthDownPeriod atomic.Uint32
+	BandwidthUpAll      atomic.Uint64 // 使用上行带宽总量
+	BandwidthDownAll    atomic.Uint64 // 使用下行带宽总量
 	closeOnce           sync.Once
 	CloseChan           chan struct{}
-	LastDataTime        atomic2.Time // 最后数据传输时间
+	LastDataTime        atomic.Int64 // 最后数据传输时间
 	PayloadIn           chan *Payload
 	PayloadOutCstp      chan *Payload // Cstp的数据
 	PayloadOutDtls      chan *Payload // Dtls的数据
@@ -220,7 +219,7 @@ func (s *Session) NewConn() *ConnSession {
 		PayloadOutDtls: make(chan *Payload, 64),
 		dSess:          &atomic.Value{},
 	}
-	cSess.LastDataTime.Store(time.Now())
+	cSess.LastDataTime.Store(time.Now().Unix())
 
 	dSess := &DtlsSession{
 		isActive: -1,