Compare commits

...
9 Commits
Author SHA1 Message Date
TenderIronh 2275620060 dartnode 2025-06-10 15:12:53 +08:00
TenderIronh 29faf4a950 nil pointer 2025-02-04 23:10:47 +08:00
TenderIronh 080e6af779 fix public ip detect bug 2024-12-02 21:10:15 +08:00
TenderIronh 77bfa45172 portmap loss & android ipv6 failed & public ip detect 2024-11-21 10:31:07 +08:00
TenderIronh 3616768682 rename 2024-11-21 10:29:06 +08:00
TenderIronh f015b828fc specified gomobile version 2024-10-20 21:33:20 +08:00
TenderIronh df1e16e708 3.21.8 2024-10-20 11:33:07 +08:00
W192547975 c68094cc12 CertPool Fix (#96)
Remove caCertPool errCert “else” in p2pnetwork.go
2024-08-02 14:23:47 +08:00
CAESIUS_TIM a0df0b1e95 [doc ]no bare urls (#80) 2024-08-02 14:22:31 +08:00
24 changed files with 294 additions and 139 deletions
+2 -1
View File
@@ -20,4 +20,5 @@ wintun.dll
.vscode/ .vscode/
app/.idea/ app/.idea/
*_debug_bin* *_debug_bin*
cmd/openp2p cmd/openp2p
vendor/
+2 -2
View File
@@ -31,7 +31,7 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
## 快速入门 ## 快速入门
仅需简单4步就能用起来。 仅需简单4步就能用起来。
下面是一个远程办公例子:在家里连入办公室Windows电脑。 下面是一个远程办公例子:在家里连入办公室Windows电脑。
(另外一个快速入门视频 https://www.bilibili.com/video/BV1Et4y1P7bF/ (另外一个快速入门视频 <https://www.bilibili.com/video/BV1Et4y1P7bF/>
### 1.注册 ### 1.注册
前往<https://console.openp2p.cn> 注册新用户,暂无需任何认证 前往<https://console.openp2p.cn> 注册新用户,暂无需任何认证
@@ -96,7 +96,7 @@ Windows默认会阻止没有花钱买它家证书签名过的程序,选择“
服务端有个调度模型,根据带宽、ping值、稳定性、服务时长,尽可能地使共享节点均匀地提供服务。连接共享节点使用TOTP密码,hmac-sha256算法校验,它是一次性密码,和我们平时使用的手机验证码或银行密码器一样的原理。 服务端有个调度模型,根据带宽、ping值、稳定性、服务时长,尽可能地使共享节点均匀地提供服务。连接共享节点使用TOTP密码,hmac-sha256算法校验,它是一次性密码,和我们平时使用的手机验证码或银行密码器一样的原理。
## 编译 ## 编译
go version go1.18.1+ go version 1.20 only (支持win7)
cd到代码根目录,执行 cd到代码根目录,执行
``` ```
make make
+3 -1
View File
@@ -103,7 +103,7 @@ That's right, the relay node is naturally an man-in-middle, so AES encryption is
The server side has a scheduling model, which calculate bandwith, ping value,stability and service duration to provide a well-proportioned service to every share node. It uses TOTP(Time-based One-time Password) with hmac-sha256 algorithem, its theory as same as the cellphone validation code or bank cipher coder. The server side has a scheduling model, which calculate bandwith, ping value,stability and service duration to provide a well-proportioned service to every share node. It uses TOTP(Time-based One-time Password) with hmac-sha256 algorithem, its theory as same as the cellphone validation code or bank cipher coder.
## Build ## Build
go version go1.18.1+ go version 1.20 only (support win7)
cd root directory of the socure code and execute cd root directory of the socure code and execute
``` ```
make make
@@ -162,3 +162,5 @@ Email: [email protected] [email protected]
## Disclaimer ## Disclaimer
This project is open source for everyone to learn and use for free. It is forbidden to be used for illegal purposes. Any loss caused by improper use of this project or accident, this project and related personnel will not bear any responsibility. This project is open source for everyone to learn and use for free. It is forbidden to be used for illegal purposes. Any loss caused by improper use of this project or accident, this project and related personnel will not bear any responsibility.
## Thanks
[![Powered by DartNode](https://dartnode.com/branding/DN-Open-Source-sm.png)](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
+3 -2
View File
@@ -2,9 +2,10 @@
depends on openjdk 11, gradle 8.1.3, ndk 21 depends on openjdk 11, gradle 8.1.3, ndk 21
``` ```
go install golang.org/x/mobile/cmd/gomobile@latest # latest version not support go1.20
go install golang.org/x/mobile/cmd/gomobile@7c4916698cc93475ebfea76748ee0faba2deb2a5
gomobile init gomobile init
go get -v golang.org/x/mobile/bind go get -v golang.org/x/mobile/bind@7c4916698cc93475ebfea76748ee0faba2deb2a5
cd core cd core
gomobile bind -target android -v gomobile bind -target android -v
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
@@ -203,7 +203,8 @@ class OpenP2PService : VpnService() {
val network = Network(id, name, gateway, nodeList) val network = Network(id, name, gateway, nodeList)
println(network) println(network)
Log.i(OpenP2PService.LOG_TAG, "onBind"); Log.i(OpenP2PService.LOG_TAG, "onBind");
builder.addDnsServer("8.8.8.8") builder.addDnsServer("223.5.5.5")
builder.addDnsServer("2400:3200::1") // alicloud dns v6 & v4
builder.addRoute("10.2.3.0", 24) builder.addRoute("10.2.3.0", 24)
// builder.addRoute("0.0.0.0", 0); // builder.addRoute("0.0.0.0", 0);
builder.setSession(LOG_TAG!!) builder.setSession(LOG_TAG!!)
+13
View File
@@ -1,6 +1,7 @@
package openp2p package openp2p
import ( import (
"fmt"
"log" "log"
"testing" "testing"
) )
@@ -114,3 +115,15 @@ func TestIsIPv6(t *testing.T) {
} }
} }
} }
func TestNodeID(t *testing.T) {
node1 := "n1-stable"
node2 := "tony-stable"
nodeID1 := NodeNameToID(node1)
nodeID2 := NodeNameToID(node2)
if nodeID1 < nodeID2 {
fmt.Printf("%s < %s\n", node1, node2)
} else {
fmt.Printf("%s >= %s\n", node1, node2)
}
}
+20 -18
View File
@@ -78,12 +78,13 @@ type Config struct {
Apps []*AppConfig `json:"apps"` Apps []*AppConfig `json:"apps"`
LogLevel int LogLevel int
MaxLogSize int
daemonMode bool daemonMode bool
mtx sync.Mutex mtx sync.Mutex
sdwanMtx sync.Mutex sdwanMtx sync.Mutex
sdwan SDWANInfo sdwan SDWANInfo
delNodes []SDWANNode delNodes []*SDWANNode
addNodes []SDWANNode addNodes []*SDWANNode
} }
func (c *Config) getSDWAN() SDWANInfo { func (c *Config) getSDWAN() SDWANInfo {
@@ -92,23 +93,30 @@ func (c *Config) getSDWAN() SDWANInfo {
return c.sdwan return c.sdwan
} }
func (c *Config) getDelNodes() []SDWANNode { func (c *Config) getDelNodes() []*SDWANNode {
c.sdwanMtx.Lock() c.sdwanMtx.Lock()
defer c.sdwanMtx.Unlock() defer c.sdwanMtx.Unlock()
return c.delNodes return c.delNodes
} }
func (c *Config) getAddNodes() []SDWANNode { func (c *Config) getAddNodes() []*SDWANNode {
c.sdwanMtx.Lock() c.sdwanMtx.Lock()
defer c.sdwanMtx.Unlock() defer c.sdwanMtx.Unlock()
return c.addNodes return c.addNodes
} }
func (c *Config) resetSDWAN() {
c.sdwanMtx.Lock()
defer c.sdwanMtx.Unlock()
c.delNodes = []*SDWANNode{}
c.addNodes = []*SDWANNode{}
c.sdwan = SDWANInfo{}
}
func (c *Config) setSDWAN(s SDWANInfo) { func (c *Config) setSDWAN(s SDWANInfo) {
c.sdwanMtx.Lock() c.sdwanMtx.Lock()
defer c.sdwanMtx.Unlock() defer c.sdwanMtx.Unlock()
// get old-new // get old-new
c.delNodes = []SDWANNode{} c.delNodes = []*SDWANNode{}
for _, oldNode := range c.sdwan.Nodes { for _, oldNode := range c.sdwan.Nodes {
isDeleted := true isDeleted := true
for _, newNode := range s.Nodes { for _, newNode := range s.Nodes {
@@ -122,7 +130,7 @@ func (c *Config) setSDWAN(s SDWANInfo) {
} }
} }
// get new-old // get new-old
c.addNodes = []SDWANNode{} c.addNodes = []*SDWANNode{}
for _, newNode := range s.Nodes { for _, newNode := range s.Nodes {
isNew := true isNew := true
for _, oldNode := range c.sdwan.Nodes { for _, oldNode := range c.sdwan.Nodes {
@@ -230,17 +238,8 @@ func (c *Config) delete(app AppConfig) {
defer c.mtx.Unlock() defer c.mtx.Unlock()
defer c.save() defer c.save()
for i := 0; i < len(c.Apps); i++ { for i := 0; i < len(c.Apps); i++ {
got := false if (app.SrcPort != 0 && c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort) || // normal app
if app.SrcPort != 0 { // normal p2papp (app.SrcPort == 0 && c.Apps[i].SrcPort == 0 && c.Apps[i].PeerNode == app.PeerNode) { // memapp
if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort {
got = true
}
} else { // memapp
if c.Apps[i].PeerNode == app.PeerNode {
got = true
}
}
if got {
if i == len(c.Apps)-1 { if i == len(c.Apps)-1 {
c.Apps = c.Apps[:i] c.Apps = c.Apps[:i]
} else { } else {
@@ -249,7 +248,6 @@ func (c *Config) delete(app AppConfig) {
return return
} }
} }
} }
func (c *Config) save() { func (c *Config) save() {
@@ -280,6 +278,7 @@ func (c *Config) saveCache() {
func init() { func init() {
gConf.LogLevel = int(LvINFO) gConf.LogLevel = int(LvINFO)
gConf.MaxLogSize = 1024 * 1024
gConf.Network.ShareBandwidth = 10 gConf.Network.ShareBandwidth = 10
gConf.Network.ServerHost = "api.openp2p.cn" gConf.Network.ServerHost = "api.openp2p.cn"
gConf.Network.ServerPort = WsPort gConf.Network.ServerPort = WsPort
@@ -463,6 +462,9 @@ func parseParams(subCommand string, cmd string) {
if f.Name == "loglevel" { if f.Name == "loglevel" {
gConf.LogLevel = *logLevel gConf.LogLevel = *logLevel
} }
if f.Name == "maxlogsize" {
gConf.MaxLogSize = *maxLogSize
}
if f.Name == "tcpport" { if f.Name == "tcpport" {
gConf.Network.TCPPort = *tcpPort gConf.Network.TCPPort = *tcpPort
} }
+7 -2
View File
@@ -60,6 +60,7 @@ func (d *daemon) run() {
break break
} }
} }
args = append(args, "-nv") args = append(args, "-nv")
for { for {
// start worker // start worker
@@ -72,6 +73,7 @@ func (d *daemon) run() {
} }
gLog.Println(LvINFO, "start worker process, args:", args) gLog.Println(LvINFO, "start worker process, args:", args)
execSpec := &os.ProcAttr{Env: append(os.Environ(), "GOTRACEBACK=crash"), Files: []*os.File{os.Stdin, os.Stdout, f}} execSpec := &os.ProcAttr{Env: append(os.Environ(), "GOTRACEBACK=crash"), Files: []*os.File{os.Stdin, os.Stdout, f}}
lastRebootTime := time.Now()
p, err := os.StartProcess(binPath, args, execSpec) p, err := os.StartProcess(binPath, args, execSpec)
if err != nil { if err != nil {
gLog.Printf(LvERROR, "start worker error:%s", err) gLog.Printf(LvERROR, "start worker error:%s", err)
@@ -88,8 +90,11 @@ func (d *daemon) run() {
if !d.running { if !d.running {
return return
} }
gLog.Printf(LvERROR, "worker stop, restart it after 10s") if time.Since(lastRebootTime) < time.Second*10 {
time.Sleep(time.Second * 10) gLog.Printf(LvERROR, "worker stop, restart it after 10s")
time.Sleep(time.Second * 10)
}
} }
} }
+15 -15
View File
@@ -13,12 +13,12 @@ import (
func handshakeC2C(t *P2PTunnel) (err error) { func handshakeC2C(t *P2PTunnel) (err error) {
gLog.Printf(LvDEBUG, "handshakeC2C %s:%d:%d to %s:%d", gConf.Network.Node, t.coneLocalPort, t.coneNatPort, t.config.peerIP, t.config.peerConeNatPort) gLog.Printf(LvDEBUG, "handshakeC2C %s:%d:%d to %s:%d", gConf.Network.Node, t.coneLocalPort, t.coneNatPort, t.config.peerIP, t.config.peerConeNatPort)
defer gLog.Printf(LvDEBUG, "handshakeC2C end") defer gLog.Printf(LvDEBUG, "handshakeC2C end")
conn, err := net.ListenUDP("udp", t.la) conn, err := net.ListenUDP("udp", t.localHoleAddr)
if err != nil { if err != nil {
return err return err
} }
defer conn.Close() defer conn.Close()
_, err = UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshake, P2PHandshakeReq{ID: t.id}) _, err = UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshake, P2PHandshakeReq{ID: t.id})
if err != nil { if err != nil {
gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshake error:", err) gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshake error:", err)
return err return err
@@ -28,7 +28,7 @@ func handshakeC2C(t *P2PTunnel) (err error) {
gLog.Println(LvDEBUG, "handshakeC2C read MsgPunchHandshake error:", err) gLog.Println(LvDEBUG, "handshakeC2C read MsgPunchHandshake error:", err)
return err return err
} }
t.ra, _ = net.ResolveUDPAddr("udp", ra.String()) t.remoteHoleAddr, _ = net.ResolveUDPAddr("udp", ra.String())
var tunnelID uint64 var tunnelID uint64
if len(buff) > openP2PHeaderSize { if len(buff) > openP2PHeaderSize {
req := P2PHandshakeReq{} req := P2PHandshakeReq{}
@@ -40,7 +40,7 @@ func handshakeC2C(t *P2PTunnel) (err error) {
} }
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == t.id { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == t.id {
gLog.Printf(LvDEBUG, "read %d handshake ", t.id) gLog.Printf(LvDEBUG, "read %d handshake ", t.id)
UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
_, head, _, _, err = UDPRead(conn, HandshakeTimeout) _, head, _, _, err = UDPRead(conn, HandshakeTimeout)
if err != nil { if err != nil {
gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshakeAck error", err) gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshakeAck error", err)
@@ -49,7 +49,7 @@ func handshakeC2C(t *P2PTunnel) (err error) {
} }
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck && tunnelID == t.id { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck && tunnelID == t.id {
gLog.Printf(LvDEBUG, "read %d handshake ack ", t.id) gLog.Printf(LvDEBUG, "read %d handshake ack ", t.id)
_, err = UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) _, err = UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
if err != nil { if err != nil {
gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshakeAck error", err) gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshakeAck error", err)
return err return err
@@ -70,7 +70,7 @@ func handshakeC2S(t *P2PTunnel) error {
startTime := time.Now() startTime := time.Now()
r := rand.New(rand.NewSource(time.Now().UnixNano())) r := rand.New(rand.NewSource(time.Now().UnixNano()))
randPorts := r.Perm(65532) randPorts := r.Perm(65532)
conn, err := net.ListenUDP("udp", t.la) conn, err := net.ListenUDP("udp", t.localHoleAddr)
if err != nil { if err != nil {
return err return err
} }
@@ -111,7 +111,7 @@ func handshakeC2S(t *P2PTunnel) error {
gLog.Println(LvERROR, "parse p2pheader error:", err) gLog.Println(LvERROR, "parse p2pheader error:", err)
return err return err
} }
t.ra, _ = net.ResolveUDPAddr("udp", dst.String()) t.remoteHoleAddr, _ = net.ResolveUDPAddr("udp", dst.String())
var tunnelID uint64 var tunnelID uint64
if len(buff) > openP2PHeaderSize { if len(buff) > openP2PHeaderSize {
req := P2PHandshakeReq{} req := P2PHandshakeReq{}
@@ -123,7 +123,7 @@ func handshakeC2S(t *P2PTunnel) error {
} }
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == t.id { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == t.id {
gLog.Printf(LvDEBUG, "handshakeC2S read %d handshake ", t.id) gLog.Printf(LvDEBUG, "handshakeC2S read %d handshake ", t.id)
UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
for { for {
_, head, buff, _, err = UDPRead(conn, HandshakeTimeout) _, head, buff, _, err = UDPRead(conn, HandshakeTimeout)
if err != nil { if err != nil {
@@ -146,8 +146,8 @@ func handshakeC2S(t *P2PTunnel) error {
} }
} }
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck {
gLog.Printf(LvDEBUG, "handshakeC2S read %d handshake ack %s", t.id, t.ra.String()) gLog.Printf(LvDEBUG, "handshakeC2S read %d handshake ack %s", t.id, t.remoteHoleAddr.String())
_, err = UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) _, err = UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
return err return err
} else { } else {
gLog.Println(LvDEBUG, "handshakeS2C read msg but not MsgPunchHandshakeAck") gLog.Println(LvDEBUG, "handshakeS2C read msg but not MsgPunchHandshakeAck")
@@ -178,7 +178,7 @@ func handshakeS2C(t *P2PTunnel) error {
return err return err
} }
defer conn.Close() defer conn.Close()
UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshake, P2PHandshakeReq{ID: t.id}) UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshake, P2PHandshakeReq{ID: t.id})
_, head, buff, _, err := UDPRead(conn, HandshakeTimeout) _, head, buff, _, err := UDPRead(conn, HandshakeTimeout)
if err != nil { if err != nil {
// gLog.Println(LevelDEBUG, "one of the handshake error:", err) // gLog.Println(LevelDEBUG, "one of the handshake error:", err)
@@ -199,7 +199,7 @@ func handshakeS2C(t *P2PTunnel) error {
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == t.id { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == t.id {
gLog.Printf(LvDEBUG, "handshakeS2C read %d handshake ", t.id) gLog.Printf(LvDEBUG, "handshakeS2C read %d handshake ", t.id)
UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
// may read several MsgPunchHandshake // may read several MsgPunchHandshake
for { for {
_, head, buff, _, err = UDPRead(conn, HandshakeTimeout) _, head, buff, _, err = UDPRead(conn, HandshakeTimeout)
@@ -224,7 +224,7 @@ func handshakeS2C(t *P2PTunnel) error {
} }
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck { if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck {
gLog.Printf(LvDEBUG, "handshakeS2C read %d handshake ack %s", t.id, conn.LocalAddr().String()) gLog.Printf(LvDEBUG, "handshakeS2C read %d handshake ack %s", t.id, conn.LocalAddr().String())
UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id}) UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
gotIt = true gotIt = true
la, _ := net.ResolveUDPAddr("udp", conn.LocalAddr().String()) la, _ := net.ResolveUDPAddr("udp", conn.LocalAddr().String())
gotCh <- la gotCh <- la
@@ -238,14 +238,14 @@ func handshakeS2C(t *P2PTunnel) error {
gLog.Printf(LvDEBUG, "send symmetric handshake end") gLog.Printf(LvDEBUG, "send symmetric handshake end")
if compareVersion(t.config.peerVersion, SymmetricSimultaneouslySendVersion) < 0 { // compatible with old client if compareVersion(t.config.peerVersion, SymmetricSimultaneouslySendVersion) < 0 { // compatible with old client
gLog.Println(LvDEBUG, "handshakeS2C ready, notify peer connect") gLog.Println(LvDEBUG, "handshakeS2C ready, notify peer connect")
t.pn.push(t.config.PeerNode, MsgPushHandshakeStart, TunnelMsg{ID: t.id}) GNetwork.push(t.config.PeerNode, MsgPushHandshakeStart, TunnelMsg{ID: t.id})
} }
select { select {
case <-time.After(HandshakeTimeout): case <-time.After(HandshakeTimeout):
return fmt.Errorf("wait handshake timeout") return fmt.Errorf("wait handshake timeout")
case la := <-gotCh: case la := <-gotCh:
t.la = la t.localHoleAddr = la
gLog.Println(LvDEBUG, "symmetric handshake ok", la) gLog.Println(LvDEBUG, "symmetric handshake ok", la)
gLog.Printf(LvINFO, "handshakeS2C ok. cost %dms", time.Since(startTime)/time.Millisecond) gLog.Printf(LvINFO, "handshakeS2C ok. cost %dms", time.Since(startTime)/time.Millisecond)
} }
+22 -18
View File
@@ -66,7 +66,7 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
} }
// The connection can write data to the desired address. // The connection can write data to the desired address.
msg, err := newMessage(MsgNATDetect, 0, nil) msg, err := newMessage(MsgNATDetect, MsgNAT, nil)
_, err = conn.WriteTo(msg, dst) _, err = conn.WriteTo(msg, dst)
if err != nil { if err != nil {
return "", 0, err return "", 0, err
@@ -121,18 +121,6 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
return return
} }
defer echoConn.Close() defer echoConn.Close()
go func() {
// close outside for breaking the ReadFromUDP
// wait 30s for echo testing
buf := make([]byte, 1600)
echoConn.SetReadDeadline(time.Now().Add(time.Second * 30))
n, addr, err := echoConn.ReadFromUDP(buf)
if err != nil {
return
}
echoConn.WriteToUDP(buf[0:n], addr)
gLog.Println(LvDEBUG, "echo server end")
}()
// testing for public ip // testing for public ip
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
if i == 1 { if i == 1 {
@@ -164,17 +152,33 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
break break
} }
defer conn.Close() defer conn.Close()
dst, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", publicIP, echoPort)) dst, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", gConf.Network.ServerHost, gConf.Network.ServerPort))
if err != nil { if err != nil {
break break
} }
conn.WriteTo([]byte("echo"), dst)
// The connection can write data to the desired address.
msg, _ := newMessage(MsgNATDetect, MsgPublicIP, NatDetectReq{EchoPort: echoPort})
_, err = conn.WriteTo(msg, dst)
if err != nil {
continue
}
buf := make([]byte, 1600) buf := make([]byte, 1600)
// wait for echo testing // wait for echo testing
conn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout)) echoConn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout))
_, _, err = conn.ReadFromUDP(buf) nRead, _, err := echoConn.ReadFromUDP(buf)
if err == nil { if err != nil {
gLog.Println(LvDEBUG, "PublicIP detect error:", err)
continue
}
natRsp := NatDetectRsp{}
err = json.Unmarshal(buf[openP2PHeaderSize:nRead], &natRsp)
if err != nil {
gLog.Println(LvDEBUG, "PublicIP detect error:", err)
continue
}
if natRsp.Port == echoPort {
if i == 1 { if i == 1 {
gLog.Println(LvDEBUG, "UPNP or NAT-PMP:YES") gLog.Println(LvDEBUG, "UPNP or NAT-PMP:YES")
hasUPNPorNATPMP = 1 hasUPNPorNATPMP = 1
+7 -6
View File
@@ -52,7 +52,7 @@ func addRoute(dst, gw, ifname string) error {
} }
func delRoute(dst, gw string) error { func delRoute(dst, gw string) error {
err := exec.Command("route", "delete", dst, gw).Run() err := exec.Command("route", "delete", dst, "-gateway", gw).Run()
return err return err
} }
func delRoutesByGateway(gateway string) error { func delRoutesByGateway(gateway string) error {
@@ -68,13 +68,14 @@ func delRoutesByGateway(gateway string) error {
continue continue
} }
fields := strings.Fields(line) fields := strings.Fields(line)
if len(fields) >= 7 && fields[0] == "default" && fields[len(fields)-1] == gateway { if len(fields) >= 2 {
delCmd := exec.Command("route", "delete", "default", gateway) cmd := exec.Command("route", "delete", fields[0], gateway)
err := delCmd.Run() err := cmd.Run()
if err != nil { if err != nil {
return err gLog.Printf(LvERROR, "Delete route %s error:%s", fields[0], err)
continue
} }
fmt.Printf("Delete route ok: %s %s\n", "default", gateway) gLog.Printf(LvINFO, "Delete route ok: %s %s\n", fields[0], gateway)
} }
} }
return nil return nil
+3 -2
View File
@@ -124,9 +124,10 @@ func delRoutesByGateway(gateway string) error {
delCmd := exec.Command("route", "del", "-net", fields[0], "gw", gateway) delCmd := exec.Command("route", "del", "-net", fields[0], "gw", gateway)
err := delCmd.Run() err := delCmd.Run()
if err != nil { if err != nil {
return err gLog.Printf(LvERROR, "Delete route %s error:%s", fields[0], err)
continue
} }
fmt.Printf("Delete route ok: %s %s %s\n", fields[0], fields[1], gateway) gLog.Printf(LvINFO, "Delete route ok: %s %s %s\n", fields[0], fields[1], gateway)
} }
} }
return nil return nil
+3 -2
View File
@@ -133,9 +133,10 @@ func delRoutesByGateway(gateway string) error {
cmd := exec.Command("route", "delete", fields[0], "mask", fields[1], gateway) cmd := exec.Command("route", "delete", fields[0], "mask", fields[1], gateway)
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
fmt.Println("Delete route error:", err) gLog.Printf(LvERROR, "Delete route %s error:%s", fields[0], err)
continue
} }
fmt.Printf("Delete route ok: %s %s %s\n", fields[0], fields[1], gateway) gLog.Printf(LvINFO, "Delete route ok: %s %s %s\n", fields[0], fields[1], gateway)
} }
} }
return nil return nil
+1 -1
View File
@@ -174,7 +174,7 @@ func (app *p2pApp) buildDirectTunnel() error {
pn := GNetwork pn := GNetwork
initErr := pn.requestPeerInfo(&app.config) initErr := pn.requestPeerInfo(&app.config)
if initErr != nil { if initErr != nil {
gLog.Printf(LvERROR, "%s init error:%s", app.config.LogPeerNode(), initErr) gLog.Printf(LvERROR, "%s requestPeerInfo error:%s", app.config.LogPeerNode(), initErr)
return initErr return initErr
} }
t, err = pn.addDirectTunnel(app.config, 0) t, err = pn.addDirectTunnel(app.config, 0)
+3 -2
View File
@@ -115,6 +115,7 @@ func (pn *P2PNetwork) run() {
pn.write(MsgHeartbeat, 0, "") pn.write(MsgHeartbeat, 0, "")
case <-pn.restartCh: case <-pn.restartCh:
gLog.Printf(LvDEBUG, "got restart channel") gLog.Printf(LvDEBUG, "got restart channel")
pn.sdwan.reset()
pn.online = false pn.online = false
pn.wgReconnect.Wait() // wait read/autorunapp goroutine end pn.wgReconnect.Wait() // wait read/autorunapp goroutine end
delay := ClientAPITimeout + time.Duration(rand.Int()%pn.loginMaxDelaySeconds)*time.Second delay := ClientAPITimeout + time.Duration(rand.Int()%pn.loginMaxDelaySeconds)*time.Second
@@ -124,6 +125,7 @@ func (pn *P2PNetwork) run() {
gLog.Println(LvERROR, "P2PNetwork init error:", err) gLog.Println(LvERROR, "P2PNetwork init error:", err)
} }
gConf.retryAllApp() gConf.retryAllApp()
case t := <-pn.tunnelCloseCh: case t := <-pn.tunnelCloseCh:
gLog.Printf(LvDEBUG, "got tunnelCloseCh %s", t.config.LogPeerNode()) gLog.Printf(LvDEBUG, "got tunnelCloseCh %s", t.config.LogPeerNode())
pn.apps.Range(func(id, i interface{}) bool { pn.apps.Range(func(id, i interface{}) bool {
@@ -466,7 +468,7 @@ func (pn *P2PNetwork) newTunnel(config AppConfig, tid uint64, isClient bool) (t
} }
} }
t = &P2PTunnel{pn: pn, t = &P2PTunnel{
config: config, config: config,
id: tid, id: tid,
writeData: make(chan []byte, WriteDataChanSize), writeData: make(chan []byte, WriteDataChanSize),
@@ -533,7 +535,6 @@ func (pn *P2PNetwork) init() error {
caCertPool, errCert := x509.SystemCertPool() caCertPool, errCert := x509.SystemCertPool()
if errCert != nil { if errCert != nil {
gLog.Println(LvERROR, "Failed to load system root CAs:", errCert) gLog.Println(LvERROR, "Failed to load system root CAs:", errCert)
} else {
caCertPool = x509.NewCertPool() caCertPool = x509.NewCertPool()
} }
caCertPool.AppendCertsFromPEM([]byte(rootCA)) caCertPool.AppendCertsFromPEM([]byte(rootCA))
+37 -38
View File
@@ -19,13 +19,12 @@ const WriteDataChanSize int = 3000
var buildTunnelMtx sync.Mutex var buildTunnelMtx sync.Mutex
type P2PTunnel struct { type P2PTunnel struct {
pn *P2PNetwork
conn underlay conn underlay
hbTime time.Time hbTime time.Time
hbMtx sync.Mutex hbMtx sync.Mutex
config AppConfig config AppConfig
la *net.UDPAddr // local hole address localHoleAddr *net.UDPAddr // local hole address
ra *net.UDPAddr // remote hole address remoteHoleAddr *net.UDPAddr // remote hole address
overlayConns sync.Map // both TCP and UDP overlayConns sync.Map // both TCP and UDP
id uint64 // client side alloc rand.uint64 = server side id uint64 // client side alloc rand.uint64 = server side
running bool running bool
@@ -58,7 +57,7 @@ func (t *P2PTunnel) initPort() {
t.coneLocalPort = localPort2 t.coneLocalPort = localPort2
t.coneNatPort = natPort t.coneNatPort = natPort
} }
t.la = &net.UDPAddr{IP: net.ParseIP(gConf.Network.localIP), Port: t.coneLocalPort} t.localHoleAddr = &net.UDPAddr{IP: net.ParseIP(gConf.Network.localIP), Port: t.coneLocalPort}
gLog.Printf(LvDEBUG, "prepare punching port %d:%d", t.coneLocalPort, t.coneNatPort) gLog.Printf(LvDEBUG, "prepare punching port %d:%d", t.coneLocalPort, t.coneNatPort)
} }
@@ -85,8 +84,8 @@ func (t *P2PTunnel) connect() error {
if req.Token == 0 { // no relay token if req.Token == 0 { // no relay token
req.Token = gConf.Network.Token req.Token = gConf.Network.Token
} }
t.pn.push(t.config.PeerNode, MsgPushConnectReq, req) GNetwork.push(t.config.PeerNode, MsgPushConnectReq, req)
head, body := t.pn.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, UnderlayConnectTimeout*3) head, body := GNetwork.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, UnderlayConnectTimeout*3)
if head == nil { if head == nil {
return errors.New("connect error") return errors.New("connect error")
} }
@@ -161,7 +160,7 @@ func (t *P2PTunnel) checkActive() bool {
// call when user delete tunnel // call when user delete tunnel
func (t *P2PTunnel) close() { func (t *P2PTunnel) close() {
t.pn.NotifyTunnelClose(t) GNetwork.NotifyTunnelClose(t)
if !t.running { if !t.running {
return return
} }
@@ -169,7 +168,7 @@ func (t *P2PTunnel) close() {
if t.conn != nil { if t.conn != nil {
t.conn.Close() t.conn.Close()
} }
t.pn.allTunnels.Delete(t.id) GNetwork.allTunnels.Delete(t.id)
gLog.Printf(LvINFO, "%d p2ptunnel close %s ", t.id, t.config.LogPeerNode()) gLog.Printf(LvINFO, "%d p2ptunnel close %s ", t.id, t.config.LogPeerNode())
} }
@@ -190,7 +189,7 @@ func (t *P2PTunnel) start() error {
func (t *P2PTunnel) handshake() error { func (t *P2PTunnel) handshake() error {
if t.config.peerConeNatPort > 0 { // only peer is cone should prepare t.ra if t.config.peerConeNatPort > 0 { // only peer is cone should prepare t.ra
var err error var err error
t.ra, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", t.config.peerIP, t.config.peerConeNatPort)) t.remoteHoleAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", t.config.peerIP, t.config.peerConeNatPort))
if err != nil { if err != nil {
return err return err
} }
@@ -198,7 +197,7 @@ func (t *P2PTunnel) handshake() error {
if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 { if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 {
gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion) gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion)
} else { } else {
ts := time.Duration(int64(t.punchTs) + t.pn.dt + t.pn.ddtma*int64(time.Since(t.pn.hbTime)+PunchTsDelay)/int64(NetworkHeartbeatTime) - time.Now().UnixNano()) ts := time.Duration(int64(t.punchTs) + GNetwork.dt + GNetwork.ddtma*int64(time.Since(GNetwork.hbTime)+PunchTsDelay)/int64(NetworkHeartbeatTime) - time.Now().UnixNano())
if ts > PunchTsDelay || ts < 0 { if ts > PunchTsDelay || ts < 0 {
ts = PunchTsDelay ts = PunchTsDelay
} }
@@ -267,11 +266,11 @@ func (t *P2PTunnel) connectUnderlayUDP() (c underlay, err error) {
} }
if t.config.isUnderlayServer == 1 { if t.config.isUnderlayServer == 1 {
time.Sleep(time.Millisecond * 10) // punching udp port will need some times in some env time.Sleep(time.Millisecond * 10) // punching udp port will need some times in some env
go t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil) go GNetwork.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
if t.config.UnderlayProtocol == "kcp" { if t.config.UnderlayProtocol == "kcp" {
ul, err = listenKCP(t.la.String(), TunnelIdleTimeout) ul, err = listenKCP(t.localHoleAddr.String(), TunnelIdleTimeout)
} else { } else {
ul, err = listenQuic(t.la.String(), TunnelIdleTimeout) ul, err = listenQuic(t.localHoleAddr.String(), TunnelIdleTimeout)
} }
if err != nil { if err != nil {
@@ -293,24 +292,24 @@ func (t *P2PTunnel) connectUnderlayUDP() (c underlay, err error) {
} }
//else //else
conn, errL := net.ListenUDP("udp", t.la) conn, errL := net.ListenUDP("udp", t.localHoleAddr)
if errL != nil { if errL != nil {
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
conn, errL = net.ListenUDP("udp", t.la) conn, errL = net.ListenUDP("udp", t.localHoleAddr)
if errL != nil { if errL != nil {
return nil, fmt.Errorf("%s listen error:%s", underlayProtocol, errL) return nil, fmt.Errorf("%s listen error:%s", underlayProtocol, errL)
} }
} }
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout) GNetwork.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout)
gLog.Printf(LvDEBUG, "%s dial to %s", underlayProtocol, t.ra.String()) gLog.Printf(LvDEBUG, "%s dial to %s", underlayProtocol, t.remoteHoleAddr.String())
if t.config.UnderlayProtocol == "kcp" { if t.config.UnderlayProtocol == "kcp" {
ul, errL = dialKCP(conn, t.ra, TunnelIdleTimeout) ul, errL = dialKCP(conn, t.remoteHoleAddr, TunnelIdleTimeout)
} else { } else {
ul, errL = dialQuic(conn, t.ra, TunnelIdleTimeout) ul, errL = dialQuic(conn, t.remoteHoleAddr, TunnelIdleTimeout)
} }
if errL != nil { if errL != nil {
return nil, fmt.Errorf("%s dial to %s error:%s", underlayProtocol, t.ra.String(), errL) return nil, fmt.Errorf("%s dial to %s error:%s", underlayProtocol, t.remoteHoleAddr.String(), errL)
} }
handshakeBegin := time.Now() handshakeBegin := time.Now()
ul.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello")) ul.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
@@ -353,12 +352,12 @@ func (t *P2PTunnel) connectUnderlayTCP() (c underlay, err error) {
// client side // client side
if t.config.linkMode == LinkModeTCP4 { if t.config.linkMode == LinkModeTCP4 {
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout) GNetwork.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout)
} else { //tcp punch should sleep for punch the same time } else { //tcp punch should sleep for punch the same time
if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 { if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 {
gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion) gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion)
} else { } else {
ts := time.Duration(int64(t.punchTs) + t.pn.dt + t.pn.ddtma*int64(time.Since(t.pn.hbTime)+PunchTsDelay)/int64(NetworkHeartbeatTime) - time.Now().UnixNano()) ts := time.Duration(int64(t.punchTs) + GNetwork.dt + GNetwork.ddtma*int64(time.Since(GNetwork.hbTime)+PunchTsDelay)/int64(NetworkHeartbeatTime) - time.Now().UnixNano())
if ts > PunchTsDelay || ts < 0 { if ts > PunchTsDelay || ts < 0 {
ts = PunchTsDelay ts = PunchTsDelay
} }
@@ -394,7 +393,7 @@ func (t *P2PTunnel) connectUnderlayTCP() (c underlay, err error) {
func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) { func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) {
gLog.Printf(LvDEBUG, "connectUnderlayTCPSymmetric %s start ", t.config.LogPeerNode()) gLog.Printf(LvDEBUG, "connectUnderlayTCPSymmetric %s start ", t.config.LogPeerNode())
defer gLog.Printf(LvDEBUG, "connectUnderlayTCPSymmetric %s end ", t.config.LogPeerNode()) defer gLog.Printf(LvDEBUG, "connectUnderlayTCPSymmetric %s end ", t.config.LogPeerNode())
ts := time.Duration(int64(t.punchTs) + t.pn.dt + t.pn.ddtma*int64(time.Since(t.pn.hbTime)+PunchTsDelay)/int64(NetworkHeartbeatTime) - time.Now().UnixNano()) ts := time.Duration(int64(t.punchTs) + GNetwork.dt + GNetwork.ddtma*int64(time.Since(GNetwork.hbTime)+PunchTsDelay)/int64(NetworkHeartbeatTime) - time.Now().UnixNano())
if ts > PunchTsDelay || ts < 0 { if ts > PunchTsDelay || ts < 0 {
ts = PunchTsDelay ts = PunchTsDelay
} }
@@ -426,7 +425,7 @@ func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) {
} }
_, buff, err := ul.ReadBuffer() _, buff, err := ul.ReadBuffer()
if err != nil { if err != nil {
gLog.Printf(LvERROR, "utcp.ReadBuffer error:", err) gLog.Println(LvDEBUG, "c2s ul.ReadBuffer error:", err)
return return
} }
req := P2PHandshakeReq{} req := P2PHandshakeReq{}
@@ -455,7 +454,7 @@ func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) {
_, buff, err := ul.ReadBuffer() _, buff, err := ul.ReadBuffer()
if err != nil { if err != nil {
gLog.Printf(LvERROR, "utcp.ReadBuffer error:", err) gLog.Println(LvDEBUG, "s2c ul.ReadBuffer error:", err)
return return
} }
req := P2PHandshakeReq{} req := P2PHandshakeReq{}
@@ -490,7 +489,7 @@ func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
defer gLog.Printf(LvDEBUG, "connectUnderlayTCP6 %s end ", t.config.LogPeerNode()) defer gLog.Printf(LvDEBUG, "connectUnderlayTCP6 %s end ", t.config.LogPeerNode())
var ul *underlayTCP6 var ul *underlayTCP6
if t.config.isUnderlayServer == 1 { if t.config.isUnderlayServer == 1 {
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil) GNetwork.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
ul, err = listenTCP6(t.coneNatPort, UnderlayConnectTimeout) ul, err = listenTCP6(t.coneNatPort, UnderlayConnectTimeout)
if err != nil { if err != nil {
return nil, fmt.Errorf("listen TCP6 error:%s", err) return nil, fmt.Errorf("listen TCP6 error:%s", err)
@@ -509,17 +508,17 @@ func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
} }
//else //else
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout) GNetwork.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout)
gLog.Println(LvDEBUG, "TCP6 dial to ", t.config.peerIPv6) gLog.Println(LvDEBUG, "TCP6 dial to ", t.config.peerIPv6)
ul, err = dialTCP6(t.config.peerIPv6, t.config.peerConeNatPort) ul, err = dialTCP6(t.config.peerIPv6, t.config.peerConeNatPort)
if err != nil { if err != nil || ul == nil {
return nil, fmt.Errorf("TCP6 dial to %s:%d error:%s", t.config.peerIPv6, t.config.peerConeNatPort, err) return nil, fmt.Errorf("TCP6 dial to %s:%d error:%s", t.config.peerIPv6, t.config.peerConeNatPort, err)
} }
handshakeBegin := time.Now() handshakeBegin := time.Now()
ul.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello")) ul.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
_, buff, err := ul.ReadBuffer() _, buff, errR := ul.ReadBuffer()
if err != nil { if errR != nil {
return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", err) return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", errR)
} }
if buff != nil { if buff != nil {
gLog.Println(LvDEBUG, string(buff)) gLog.Println(LvDEBUG, string(buff))
@@ -596,7 +595,7 @@ func (t *P2PTunnel) readLoop() {
} }
tunnelID := binary.LittleEndian.Uint64(body[:8]) tunnelID := binary.LittleEndian.Uint64(body[:8])
gLog.Printf(LvDev, "relay data to %d, len=%d", tunnelID, head.DataLen-RelayHeaderSize) gLog.Printf(LvDev, "relay data to %d, len=%d", tunnelID, head.DataLen-RelayHeaderSize)
if err := t.pn.relay(tunnelID, body[RelayHeaderSize:]); err != nil { if err := GNetwork.relay(tunnelID, body[RelayHeaderSize:]); err != nil {
gLog.Printf(LvERROR, "%s:%d relay to %d len=%d error:%s", t.config.LogPeerNode(), t.id, tunnelID, len(body), ErrRelayTunnelNotFound) gLog.Printf(LvERROR, "%s:%d relay to %d len=%d error:%s", t.config.LogPeerNode(), t.id, tunnelID, len(body), ErrRelayTunnelNotFound)
} }
case MsgRelayHeartbeat: case MsgRelayHeartbeat:
@@ -608,7 +607,7 @@ func (t *P2PTunnel) readLoop() {
// TODO: debug relay heartbeat // TODO: debug relay heartbeat
gLog.Printf(LvDEBUG, "read MsgRelayHeartbeat from rtid:%d,appid:%d", req.RelayTunnelID, req.AppID) gLog.Printf(LvDEBUG, "read MsgRelayHeartbeat from rtid:%d,appid:%d", req.RelayTunnelID, req.AppID)
// update app hbtime // update app hbtime
t.pn.updateAppHeartbeat(req.AppID) GNetwork.updateAppHeartbeat(req.AppID)
req.From = gConf.Network.Node req.From = gConf.Network.Node
t.WriteMessage(req.RelayTunnelID, MsgP2P, MsgRelayHeartbeatAck, &req) t.WriteMessage(req.RelayTunnelID, MsgP2P, MsgRelayHeartbeatAck, &req)
case MsgRelayHeartbeatAck: case MsgRelayHeartbeatAck:
@@ -620,7 +619,7 @@ func (t *P2PTunnel) readLoop() {
} }
// TODO: debug relay heartbeat // TODO: debug relay heartbeat
gLog.Printf(LvDEBUG, "read MsgRelayHeartbeatAck to appid:%d", req.AppID) gLog.Printf(LvDEBUG, "read MsgRelayHeartbeatAck to appid:%d", req.AppID)
t.pn.updateAppHeartbeat(req.AppID) GNetwork.updateAppHeartbeat(req.AppID)
case MsgOverlayConnectReq: case MsgOverlayConnectReq:
req := OverlayConnectReq{} req := OverlayConnectReq{}
if err := json.Unmarshal(body, &req); err != nil { if err := json.Unmarshal(body, &req); err != nil {
@@ -733,7 +732,7 @@ func (t *P2PTunnel) listen() error {
FromIP: gConf.Network.publicIP, FromIP: gConf.Network.publicIP,
ConeNatPort: t.coneNatPort, ConeNatPort: t.coneNatPort,
ID: t.id, ID: t.id,
PunchTs: uint64(time.Now().UnixNano() + int64(PunchTsDelay) - t.pn.dt), PunchTs: uint64(time.Now().UnixNano() + int64(PunchTsDelay) - GNetwork.dt),
Version: OpenP2PVersion, Version: OpenP2PVersion,
} }
t.punchTs = rsp.PunchTs t.punchTs = rsp.PunchTs
@@ -742,7 +741,7 @@ func (t *P2PTunnel) listen() error {
rsp.IPv6 = gConf.IPv6() rsp.IPv6 = gConf.IPv6()
} }
t.pn.push(t.config.PeerNode, MsgPushConnectRsp, rsp) GNetwork.push(t.config.PeerNode, MsgPushConnectRsp, rsp)
gLog.Printf(LvDEBUG, "p2ptunnel wait for connecting") gLog.Printf(LvDEBUG, "p2ptunnel wait for connecting")
t.tunnelServer = true t.tunnelServer = true
return t.start() return t.start()
@@ -760,9 +759,9 @@ func (t *P2PTunnel) closeOverlayConns(appID uint64) {
func (t *P2PTunnel) handleNodeData(head *openP2PHeader, body []byte, isRelay bool) { func (t *P2PTunnel) handleNodeData(head *openP2PHeader, body []byte, isRelay bool) {
gLog.Printf(LvDev, "%d tunnel read node data bodylen=%d, relay=%t", t.id, head.DataLen, isRelay) gLog.Printf(LvDev, "%d tunnel read node data bodylen=%d, relay=%t", t.id, head.DataLen, isRelay)
ch := t.pn.nodeData ch := GNetwork.nodeData
// if body[9] == 1 { // TODO: deal relay // if body[9] == 1 { // TODO: deal relay
// ch = t.pn.nodeDataSmall // ch = GNetwork.nodeDataSmall
// gLog.Printf(LvDEBUG, "read icmp %d", time.Now().Unix()) // gLog.Printf(LvDEBUG, "read icmp %d", time.Now().Unix())
// } // }
if isRelay { if isRelay {
+87
View File
@@ -0,0 +1,87 @@
package openp2p
import (
"fmt"
"net"
"os"
"time"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
// 定义ICMP回显请求和应答的结构
type ICMPMessage struct {
Type uint8
Code uint8
Checksum uint16
Ident uint16
Seq uint16
Data []byte
}
// Ping sends an ICMP Echo request to the specified host and returns the response time.
func Ping(host string) (time.Duration, error) {
// Resolve the IP address of the host
ipAddr, err := net.ResolveIPAddr("ip4", host)
if err != nil {
return 0, fmt.Errorf("failed to resolve host: %v", err)
}
// Create an ICMP listener
conn, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
if err != nil {
return 0, fmt.Errorf("failed to create ICMP connection: %v", err)
}
defer conn.Close()
// Create an ICMP Echo request message
message := icmp.Message{
Type: ipv4.ICMPTypeEcho,
Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff,
Seq: 1,
Data: []byte("HELLO-R-U-THERE"),
},
}
// Marshal the message into binary form
messageBytes, err := message.Marshal(nil)
if err != nil {
return 0, fmt.Errorf("failed to marshal ICMP message: %v", err)
}
// Send the ICMP Echo request
start := time.Now()
if _, err := conn.WriteTo(messageBytes, ipAddr); err != nil {
return 0, fmt.Errorf("failed to send ICMP request: %v", err)
}
// Set a deadline for the response
err = conn.SetReadDeadline(time.Now().Add(3 * time.Second))
if err != nil {
return 0, fmt.Errorf("failed to set read deadline: %v", err)
}
// Read the ICMP response
response := make([]byte, 1500)
n, _, err := conn.ReadFrom(response)
if err != nil {
return 0, fmt.Errorf("failed to read ICMP response: %v", err)
}
// Parse the ICMP response message
parsedMessage, err := icmp.ParseMessage(ipv4.ICMPTypeEchoReply.Protocol(), response[:n])
if err != nil {
return 0, fmt.Errorf("failed to parse ICMP response: %v", err)
}
// Check if the response is an Echo reply
if parsedMessage.Type == ipv4.ICMPTypeEchoReply {
duration := time.Since(start)
return duration, nil
} else {
return 0, fmt.Errorf("unexpected ICMP message: %+v", parsedMessage)
}
}
+9 -3
View File
@@ -10,7 +10,7 @@ import (
"time" "time"
) )
const OpenP2PVersion = "3.19.0" const OpenP2PVersion = "3.21.12"
const ProductName string = "openp2p" const ProductName string = "openp2p"
const LeastSupportVersion = "3.0.0" const LeastSupportVersion = "3.0.0"
const SyncServerTimeVersion = "3.9.0" const SyncServerTimeVersion = "3.9.0"
@@ -167,7 +167,7 @@ const (
MaxRetry = 10 MaxRetry = 10
Cone2ConeTCPPunchMaxRetry = 1 Cone2ConeTCPPunchMaxRetry = 1
Cone2ConeUDPPunchMaxRetry = 1 Cone2ConeUDPPunchMaxRetry = 1
PublicIPEchoTimeout = time.Second * 1 PublicIPEchoTimeout = time.Second * 3
NatTestTimeout = time.Second * 5 NatTestTimeout = time.Second * 5
UDPReadTimeout = time.Second * 5 UDPReadTimeout = time.Second * 5
ClientAPITimeout = time.Second * 10 ClientAPITimeout = time.Second * 10
@@ -217,6 +217,12 @@ const (
MsgSDWANInfoRsp MsgSDWANInfoRsp
) )
// MsgNATDetect
const (
MsgNAT = iota
MsgPublicIP
)
func newMessage(mainType uint16, subType uint16, packet interface{}) ([]byte, error) { func newMessage(mainType uint16, subType uint16, packet interface{}) ([]byte, error) {
data, err := json.Marshal(packet) data, err := json.Marshal(packet)
if err != nil { if err != nil {
@@ -495,7 +501,7 @@ type SDWANInfo struct {
ForceRelay int32 `json:"forceRelay,omitempty"` ForceRelay int32 `json:"forceRelay,omitempty"`
PunchPriority int32 `json:"punchPriority,omitempty"` PunchPriority int32 `json:"punchPriority,omitempty"`
Enable int32 `json:"enable,omitempty"` Enable int32 `json:"enable,omitempty"`
Nodes []SDWANNode Nodes []*SDWANNode
} }
const ( const (
+40 -9
View File
@@ -52,18 +52,36 @@ type p2pSDWAN struct {
internalRoute *IPTree internalRoute *IPTree
} }
func (s *p2pSDWAN) reset() {
gLog.Println(LvINFO, "reset sdwan when network disconnected")
// clear sysroute
delRoutesByGateway(s.gateway.String())
// clear internel route
s.internalRoute = NewIPTree("")
// clear p2papp
for _, node := range gConf.getAddNodes() {
gConf.delete(AppConfig{SrcPort: 0, PeerNode: node.Name})
}
gConf.resetSDWAN()
}
func (s *p2pSDWAN) init(name string) error { func (s *p2pSDWAN) init(name string) error {
if gConf.getSDWAN().Gateway == "" { if gConf.getSDWAN().Gateway == "" {
gLog.Println(LvDEBUG, "not in sdwan clear all ") gLog.Println(LvDEBUG, "sdwan init: not in sdwan clear all ")
} }
if s.internalRoute == nil { if s.internalRoute == nil {
s.internalRoute = NewIPTree("") s.internalRoute = NewIPTree("")
} }
s.nodeName = name s.nodeName = name
s.gateway, s.subnet, _ = net.ParseCIDR(gConf.getSDWAN().Gateway) if gw, sn, err := net.ParseCIDR(gConf.getSDWAN().Gateway); err == nil { // preserve old gateway
s.gateway = gw
s.subnet = sn
}
for _, node := range gConf.getDelNodes() { for _, node := range gConf.getDelNodes() {
gLog.Println(LvDEBUG, "deal deleted node: ", node.Name) gLog.Println(LvDEBUG, "sdwan init: deal deleted node: ", node.Name)
gLog.Printf(LvDEBUG, "sdwan init: delRoute: %s, %s ", node.IP, s.gateway.String())
delRoute(node.IP, s.gateway.String()) delRoute(node.IP, s.gateway.String())
s.internalRoute.Del(node.IP, node.IP) s.internalRoute.Del(node.IP, node.IP)
ipNum, _ := inetAtoN(node.IP) ipNum, _ := inetAtoN(node.IP)
@@ -88,24 +106,26 @@ func (s *p2pSDWAN) init(name string) error {
} }
s.internalRoute.Del(minIP.String(), maxIP.String()) s.internalRoute.Del(minIP.String(), maxIP.String())
delRoute(ipnet.String(), s.gateway.String()) delRoute(ipnet.String(), s.gateway.String())
gLog.Printf(LvDEBUG, "sdwan init: resource delRoute: %s, %s ", ipnet.String(), s.gateway.String())
} }
} }
for _, node := range gConf.getAddNodes() { for _, node := range gConf.getAddNodes() {
gLog.Println(LvDEBUG, "deal add node: ", node.Name) gLog.Println(LvDEBUG, "sdwan init: deal add node: ", node.Name)
ipNet := &net.IPNet{ ipNet := &net.IPNet{
IP: net.ParseIP(node.IP), IP: net.ParseIP(node.IP),
Mask: s.subnet.Mask, Mask: s.subnet.Mask,
} }
if node.Name == s.nodeName { if node.Name == s.nodeName {
s.virtualIP = ipNet s.virtualIP = ipNet
gLog.Println(LvINFO, "start tun ", ipNet.String()) gLog.Println(LvINFO, "sdwan init: start tun ", ipNet.String())
err := s.StartTun() err := s.StartTun()
if err != nil { if err != nil {
gLog.Println(LvERROR, "start tun error:", err) gLog.Println(LvERROR, "sdwan init: start tun error:", err)
return err return err
} }
gLog.Println(LvINFO, "start tun ok") gLog.Println(LvINFO, "sdwan init: start tun ok")
allowTunForward() allowTunForward()
gLog.Printf(LvDEBUG, "sdwan init: addRoute %s %s %s", s.subnet.String(), s.gateway.String(), s.tun.tunName)
addRoute(s.subnet.String(), s.gateway.String(), s.tun.tunName) addRoute(s.subnet.String(), s.gateway.String(), s.tun.tunName)
// addRoute("255.255.255.255/32", s.gateway.String(), s.tun.tunName) // for broadcast // addRoute("255.255.255.255/32", s.gateway.String(), s.tun.tunName) // for broadcast
// addRoute("224.0.0.0/4", s.gateway.String(), s.tun.tunName) // for multicast // addRoute("224.0.0.0/4", s.gateway.String(), s.tun.tunName) // for multicast
@@ -124,18 +144,28 @@ func (s *p2pSDWAN) init(name string) error {
continue continue
} }
if len(node.Resource) > 0 { if len(node.Resource) > 0 {
gLog.Printf(LvINFO, "deal add node: %s resource: %s", node.Name, node.Resource) gLog.Printf(LvINFO, "sdwan init: deal add node: %s resource: %s", node.Name, node.Resource)
arr := strings.Split(node.Resource, ",") arr := strings.Split(node.Resource, ",")
for _, r := range arr { for _, r := range arr {
// add internal route // add internal route
_, ipnet, err := net.ParseCIDR(r) _, ipnet, err := net.ParseCIDR(r)
if err != nil { if err != nil {
fmt.Println("Error parsing CIDR:", err) fmt.Println("sdwan init: Error parsing CIDR:", err)
continue continue
} }
if ipnet.Contains(net.ParseIP(gConf.Network.localIP)) { // local ip and resource in the same lan if ipnet.Contains(net.ParseIP(gConf.Network.localIP)) { // local ip and resource in the same lan
gLog.Printf(LvDEBUG, "sdwan init: local ip %s in this resource %s, ignore", gConf.Network.localIP, ipnet.IP.String())
continue continue
} }
// local net could access this single ip
if ipnet.Mask[0] == 255 && ipnet.Mask[1] == 255 && ipnet.Mask[2] == 255 && ipnet.Mask[3] == 255 {
gLog.Printf(LvDEBUG, "sdwan init: ping %s start", ipnet.IP.String())
if _, err := Ping(ipnet.IP.String()); err == nil {
gLog.Printf(LvDEBUG, "sdwan init: ping %s ok, ignore this resource", ipnet.IP.String())
continue
}
gLog.Printf(LvDEBUG, "sdwan init: ping %s failed", ipnet.IP.String())
}
minIP := ipnet.IP minIP := ipnet.IP
maxIP := make(net.IP, len(minIP)) maxIP := make(net.IP, len(minIP))
copy(maxIP, minIP) copy(maxIP, minIP)
@@ -144,6 +174,7 @@ func (s *p2pSDWAN) init(name string) error {
} }
s.internalRoute.Add(minIP.String(), maxIP.String(), &sdwanNode{name: node.Name, id: NodeNameToID(node.Name)}) s.internalRoute.Add(minIP.String(), maxIP.String(), &sdwanNode{name: node.Name, id: NodeNameToID(node.Name)})
// add sys route // add sys route
gLog.Printf(LvDEBUG, "sdwan init: addRoute %s %s %s", ipnet.String(), s.gateway.String(), s.tun.tunName)
addRoute(ipnet.String(), s.gateway.String(), s.tun.tunName) addRoute(ipnet.String(), s.gateway.String(), s.tun.tunName)
} }
} }
+1 -1
View File
@@ -27,7 +27,7 @@ func DefaultReadBuffer(ul underlay) (*openP2PHeader, []byte, error) {
return nil, nil, err return nil, nil, err
} }
head, err := decodeHeader(headBuf) head, err := decodeHeader(headBuf)
if err != nil { if err != nil || head.MainType > 16 {
return nil, nil, err return nil, nil, err
} }
dataBuf := make([]byte, head.DataLen) dataBuf := make([]byte, head.DataLen)
+2 -2
View File
@@ -51,7 +51,7 @@ func listenTCP(host string, port int, localPort int, mode string, t *P2PTunnel)
if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 { if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 {
gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion) gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion)
} else { } else {
ts := time.Duration(int64(t.punchTs) + t.pn.dt - time.Now().UnixNano()) ts := time.Duration(int64(t.punchTs) + GNetwork.dt - time.Now().UnixNano())
gLog.Printf(LvDEBUG, "sleep %d ms", ts/time.Millisecond) gLog.Printf(LvDEBUG, "sleep %d ms", ts/time.Millisecond)
time.Sleep(ts) time.Sleep(ts)
} }
@@ -72,7 +72,7 @@ func listenTCP(host string, port int, localPort int, mode string, t *P2PTunnel)
utcp.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, buff) utcp.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, buff)
return utcp, nil return utcp, nil
} }
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil) GNetwork.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
tid := t.id tid := t.id
if compareVersion(t.config.peerVersion, PublicIPVersion) < 0 { // old version if compareVersion(t.config.peerVersion, PublicIPVersion) < 0 { // old version
ipBytes := net.ParseIP(t.config.peerIP).To4() ipBytes := net.ParseIP(t.config.peerIP).To4()
+1 -1
View File
@@ -47,7 +47,7 @@ func (vl *v4Listener) handleConnection(c net.Conn) {
utcp.SetReadDeadline(time.Now().Add(UnderlayTCPConnectTimeout)) utcp.SetReadDeadline(time.Now().Add(UnderlayTCPConnectTimeout))
_, buff, err := utcp.ReadBuffer() _, buff, err := utcp.ReadBuffer()
if err != nil { if err != nil {
gLog.Printf(LvERROR, "utcp.ReadBuffer error:", err) gLog.Println(LvERROR, "utcp.ReadBuffer error:", err)
} }
utcp.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, buff) utcp.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, buff)
var tid uint64 var tid uint64
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 23 KiB

+11 -12
View File
@@ -8,17 +8,16 @@ require (
github.com/openp2p-cn/go-reuseport v0.3.2 github.com/openp2p-cn/go-reuseport v0.3.2
github.com/openp2p-cn/service v1.0.0 github.com/openp2p-cn/service v1.0.0
github.com/openp2p-cn/totp v0.0.0-20230421034602-0f3320ffb25e github.com/openp2p-cn/totp v0.0.0-20230421034602-0f3320ffb25e
github.com/openp2p-cn/wireguard-go v0.0.20240223
github.com/quic-go/quic-go v0.34.0 github.com/quic-go/quic-go v0.34.0
github.com/vishvananda/netlink v1.1.0 github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54
github.com/xtaci/kcp-go/v5 v5.5.17 github.com/xtaci/kcp-go/v5 v5.5.17
golang.org/x/sys v0.21.0 golang.org/x/sys v0.26.0
golang.zx2c4.com/wireguard/windows v0.5.3 golang.zx2c4.com/wireguard/windows v0.5.3
) )
require ( require (
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.7.0-rc.1 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/kardianos/service v1.2.2 // indirect github.com/kardianos/service v1.2.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect
@@ -30,13 +29,13 @@ require (
github.com/templexxx/cpu v0.1.0 // indirect github.com/templexxx/cpu v0.1.0 // indirect
github.com/templexxx/xorsimd v0.4.2 // indirect github.com/templexxx/xorsimd v0.4.2 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
golang.org/x/crypto v0.24.0 // indirect golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
golang.org/x/mod v0.18.0 // indirect golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.26.0 // indirect golang.org/x/net v0.30.0 // indirect
golang.org/x/tools v0.22.0 // indirect golang.org/x/tools v0.26.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect gvisor.dev/gvisor v0.0.0-20241128011400-745828301c93 // indirect
) )