mirror of
https://github.com/openp2p-cn/openp2p.git
synced 2026-05-10 16:12:44 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2275620060 | ||
|
|
29faf4a950 | ||
|
|
080e6af779 | ||
|
|
77bfa45172 | ||
|
|
3616768682 | ||
|
|
f015b828fc | ||
|
|
df1e16e708 | ||
|
|
c68094cc12 | ||
|
|
a0df0b1e95 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,4 +20,5 @@ wintun.dll
|
||||
.vscode/
|
||||
app/.idea/
|
||||
*_debug_bin*
|
||||
cmd/openp2p
|
||||
cmd/openp2p
|
||||
vendor/
|
||||
@@ -31,7 +31,7 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
|
||||
## 快速入门
|
||||
仅需简单4步就能用起来。
|
||||
下面是一个远程办公例子:在家里连入办公室Windows电脑。
|
||||
(另外一个快速入门视频 https://www.bilibili.com/video/BV1Et4y1P7bF/)
|
||||
(另外一个快速入门视频 <https://www.bilibili.com/video/BV1Et4y1P7bF/>)
|
||||
### 1.注册
|
||||
前往<https://console.openp2p.cn> 注册新用户,暂无需任何认证
|
||||
|
||||
@@ -96,7 +96,7 @@ Windows默认会阻止没有花钱买它家证书签名过的程序,选择“
|
||||
服务端有个调度模型,根据带宽、ping值、稳定性、服务时长,尽可能地使共享节点均匀地提供服务。连接共享节点使用TOTP密码,hmac-sha256算法校验,它是一次性密码,和我们平时使用的手机验证码或银行密码器一样的原理。
|
||||
|
||||
## 编译
|
||||
go version go1.18.1+
|
||||
go version 1.20 only (支持win7)
|
||||
cd到代码根目录,执行
|
||||
```
|
||||
make
|
||||
|
||||
@@ -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.
|
||||
|
||||
## Build
|
||||
go version go1.18.1+
|
||||
go version 1.20 only (support win7)
|
||||
cd root directory of the socure code and execute
|
||||
```
|
||||
make
|
||||
@@ -162,3 +162,5 @@ Email: openp2p.cn@gmail.com tenderiron@139.com
|
||||
## 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.
|
||||
|
||||
## Thanks
|
||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
||||
@@ -2,9 +2,10 @@
|
||||
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
|
||||
go get -v golang.org/x/mobile/bind
|
||||
go get -v golang.org/x/mobile/bind@7c4916698cc93475ebfea76748ee0faba2deb2a5
|
||||
cd core
|
||||
gomobile bind -target android -v
|
||||
if [[ $? -ne 0 ]]; then
|
||||
|
||||
@@ -203,7 +203,8 @@ class OpenP2PService : VpnService() {
|
||||
val network = Network(id, name, gateway, nodeList)
|
||||
println(network)
|
||||
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("0.0.0.0", 0);
|
||||
builder.setSession(LOG_TAG!!)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package openp2p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,12 +78,13 @@ type Config struct {
|
||||
Apps []*AppConfig `json:"apps"`
|
||||
|
||||
LogLevel int
|
||||
MaxLogSize int
|
||||
daemonMode bool
|
||||
mtx sync.Mutex
|
||||
sdwanMtx sync.Mutex
|
||||
sdwan SDWANInfo
|
||||
delNodes []SDWANNode
|
||||
addNodes []SDWANNode
|
||||
delNodes []*SDWANNode
|
||||
addNodes []*SDWANNode
|
||||
}
|
||||
|
||||
func (c *Config) getSDWAN() SDWANInfo {
|
||||
@@ -92,23 +93,30 @@ func (c *Config) getSDWAN() SDWANInfo {
|
||||
return c.sdwan
|
||||
}
|
||||
|
||||
func (c *Config) getDelNodes() []SDWANNode {
|
||||
func (c *Config) getDelNodes() []*SDWANNode {
|
||||
c.sdwanMtx.Lock()
|
||||
defer c.sdwanMtx.Unlock()
|
||||
return c.delNodes
|
||||
}
|
||||
|
||||
func (c *Config) getAddNodes() []SDWANNode {
|
||||
func (c *Config) getAddNodes() []*SDWANNode {
|
||||
c.sdwanMtx.Lock()
|
||||
defer c.sdwanMtx.Unlock()
|
||||
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) {
|
||||
c.sdwanMtx.Lock()
|
||||
defer c.sdwanMtx.Unlock()
|
||||
// get old-new
|
||||
c.delNodes = []SDWANNode{}
|
||||
c.delNodes = []*SDWANNode{}
|
||||
for _, oldNode := range c.sdwan.Nodes {
|
||||
isDeleted := true
|
||||
for _, newNode := range s.Nodes {
|
||||
@@ -122,7 +130,7 @@ func (c *Config) setSDWAN(s SDWANInfo) {
|
||||
}
|
||||
}
|
||||
// get new-old
|
||||
c.addNodes = []SDWANNode{}
|
||||
c.addNodes = []*SDWANNode{}
|
||||
for _, newNode := range s.Nodes {
|
||||
isNew := true
|
||||
for _, oldNode := range c.sdwan.Nodes {
|
||||
@@ -230,17 +238,8 @@ func (c *Config) delete(app AppConfig) {
|
||||
defer c.mtx.Unlock()
|
||||
defer c.save()
|
||||
for i := 0; i < len(c.Apps); i++ {
|
||||
got := false
|
||||
if app.SrcPort != 0 { // normal p2papp
|
||||
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 (app.SrcPort != 0 && c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort) || // normal app
|
||||
(app.SrcPort == 0 && c.Apps[i].SrcPort == 0 && c.Apps[i].PeerNode == app.PeerNode) { // memapp
|
||||
if i == len(c.Apps)-1 {
|
||||
c.Apps = c.Apps[:i]
|
||||
} else {
|
||||
@@ -249,7 +248,6 @@ func (c *Config) delete(app AppConfig) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *Config) save() {
|
||||
@@ -280,6 +278,7 @@ func (c *Config) saveCache() {
|
||||
|
||||
func init() {
|
||||
gConf.LogLevel = int(LvINFO)
|
||||
gConf.MaxLogSize = 1024 * 1024
|
||||
gConf.Network.ShareBandwidth = 10
|
||||
gConf.Network.ServerHost = "api.openp2p.cn"
|
||||
gConf.Network.ServerPort = WsPort
|
||||
@@ -463,6 +462,9 @@ func parseParams(subCommand string, cmd string) {
|
||||
if f.Name == "loglevel" {
|
||||
gConf.LogLevel = *logLevel
|
||||
}
|
||||
if f.Name == "maxlogsize" {
|
||||
gConf.MaxLogSize = *maxLogSize
|
||||
}
|
||||
if f.Name == "tcpport" {
|
||||
gConf.Network.TCPPort = *tcpPort
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ func (d *daemon) run() {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
args = append(args, "-nv")
|
||||
for {
|
||||
// start worker
|
||||
@@ -72,6 +73,7 @@ func (d *daemon) run() {
|
||||
}
|
||||
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}}
|
||||
lastRebootTime := time.Now()
|
||||
p, err := os.StartProcess(binPath, args, execSpec)
|
||||
if err != nil {
|
||||
gLog.Printf(LvERROR, "start worker error:%s", err)
|
||||
@@ -88,8 +90,11 @@ func (d *daemon) run() {
|
||||
if !d.running {
|
||||
return
|
||||
}
|
||||
gLog.Printf(LvERROR, "worker stop, restart it after 10s")
|
||||
time.Sleep(time.Second * 10)
|
||||
if time.Since(lastRebootTime) < time.Second*10 {
|
||||
gLog.Printf(LvERROR, "worker stop, restart it after 10s")
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
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)
|
||||
defer gLog.Printf(LvDEBUG, "handshakeC2C end")
|
||||
conn, err := net.ListenUDP("udp", t.la)
|
||||
conn, err := net.ListenUDP("udp", t.localHoleAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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 {
|
||||
gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshake error:", err)
|
||||
return err
|
||||
@@ -28,7 +28,7 @@ func handshakeC2C(t *P2PTunnel) (err error) {
|
||||
gLog.Println(LvDEBUG, "handshakeC2C read MsgPunchHandshake error:", err)
|
||||
return err
|
||||
}
|
||||
t.ra, _ = net.ResolveUDPAddr("udp", ra.String())
|
||||
t.remoteHoleAddr, _ = net.ResolveUDPAddr("udp", ra.String())
|
||||
var tunnelID uint64
|
||||
if len(buff) > openP2PHeaderSize {
|
||||
req := P2PHandshakeReq{}
|
||||
@@ -40,7 +40,7 @@ func handshakeC2C(t *P2PTunnel) (err error) {
|
||||
}
|
||||
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == 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)
|
||||
if err != nil {
|
||||
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 {
|
||||
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 {
|
||||
gLog.Println(LvDEBUG, "handshakeC2C write MsgPunchHandshakeAck error", err)
|
||||
return err
|
||||
@@ -70,7 +70,7 @@ func handshakeC2S(t *P2PTunnel) error {
|
||||
startTime := time.Now()
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
randPorts := r.Perm(65532)
|
||||
conn, err := net.ListenUDP("udp", t.la)
|
||||
conn, err := net.ListenUDP("udp", t.localHoleAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -111,7 +111,7 @@ func handshakeC2S(t *P2PTunnel) error {
|
||||
gLog.Println(LvERROR, "parse p2pheader error:", err)
|
||||
return err
|
||||
}
|
||||
t.ra, _ = net.ResolveUDPAddr("udp", dst.String())
|
||||
t.remoteHoleAddr, _ = net.ResolveUDPAddr("udp", dst.String())
|
||||
var tunnelID uint64
|
||||
if len(buff) > openP2PHeaderSize {
|
||||
req := P2PHandshakeReq{}
|
||||
@@ -123,7 +123,7 @@ func handshakeC2S(t *P2PTunnel) error {
|
||||
}
|
||||
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshake && tunnelID == 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 {
|
||||
_, head, buff, _, err = UDPRead(conn, HandshakeTimeout)
|
||||
if err != nil {
|
||||
@@ -146,8 +146,8 @@ func handshakeC2S(t *P2PTunnel) error {
|
||||
}
|
||||
}
|
||||
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck {
|
||||
gLog.Printf(LvDEBUG, "handshakeC2S read %d handshake ack %s", t.id, t.ra.String())
|
||||
_, err = UDPWrite(conn, t.ra, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
|
||||
gLog.Printf(LvDEBUG, "handshakeC2S read %d handshake ack %s", t.id, t.remoteHoleAddr.String())
|
||||
_, err = UDPWrite(conn, t.remoteHoleAddr, MsgP2P, MsgPunchHandshakeAck, P2PHandshakeReq{ID: t.id})
|
||||
return err
|
||||
} else {
|
||||
gLog.Println(LvDEBUG, "handshakeS2C read msg but not MsgPunchHandshakeAck")
|
||||
@@ -178,7 +178,7 @@ func handshakeS2C(t *P2PTunnel) error {
|
||||
return err
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
// 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 {
|
||||
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
|
||||
for {
|
||||
_, head, buff, _, err = UDPRead(conn, HandshakeTimeout)
|
||||
@@ -224,7 +224,7 @@ func handshakeS2C(t *P2PTunnel) error {
|
||||
}
|
||||
if head.MainType == MsgP2P && head.SubType == MsgPunchHandshakeAck {
|
||||
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
|
||||
la, _ := net.ResolveUDPAddr("udp", conn.LocalAddr().String())
|
||||
gotCh <- la
|
||||
@@ -238,14 +238,14 @@ func handshakeS2C(t *P2PTunnel) error {
|
||||
gLog.Printf(LvDEBUG, "send symmetric handshake end")
|
||||
if compareVersion(t.config.peerVersion, SymmetricSimultaneouslySendVersion) < 0 { // compatible with old client
|
||||
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 {
|
||||
case <-time.After(HandshakeTimeout):
|
||||
return fmt.Errorf("wait handshake timeout")
|
||||
case la := <-gotCh:
|
||||
t.la = la
|
||||
t.localHoleAddr = la
|
||||
gLog.Println(LvDEBUG, "symmetric handshake ok", la)
|
||||
gLog.Printf(LvINFO, "handshakeS2C ok. cost %dms", time.Since(startTime)/time.Millisecond)
|
||||
}
|
||||
|
||||
40
core/nat.go
40
core/nat.go
@@ -66,7 +66,7 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
@@ -121,18 +121,6 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
|
||||
return
|
||||
}
|
||||
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
|
||||
for i := 0; i < 2; i++ {
|
||||
if i == 1 {
|
||||
@@ -164,17 +152,33 @@ func publicIPTest(publicIP string, echoPort int) (hasPublicIP int, hasUPNPorNATP
|
||||
break
|
||||
}
|
||||
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 {
|
||||
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)
|
||||
|
||||
// wait for echo testing
|
||||
conn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout))
|
||||
_, _, err = conn.ReadFromUDP(buf)
|
||||
if err == nil {
|
||||
echoConn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout))
|
||||
nRead, _, err := echoConn.ReadFromUDP(buf)
|
||||
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 {
|
||||
gLog.Println(LvDEBUG, "UPNP or NAT-PMP:YES")
|
||||
hasUPNPorNATPMP = 1
|
||||
|
||||
@@ -52,7 +52,7 @@ func addRoute(dst, gw, ifname 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
|
||||
}
|
||||
func delRoutesByGateway(gateway string) error {
|
||||
@@ -68,13 +68,14 @@ func delRoutesByGateway(gateway string) error {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 7 && fields[0] == "default" && fields[len(fields)-1] == gateway {
|
||||
delCmd := exec.Command("route", "delete", "default", gateway)
|
||||
err := delCmd.Run()
|
||||
if len(fields) >= 2 {
|
||||
cmd := exec.Command("route", "delete", fields[0], gateway)
|
||||
err := cmd.Run()
|
||||
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
|
||||
|
||||
@@ -124,9 +124,10 @@ func delRoutesByGateway(gateway string) error {
|
||||
delCmd := exec.Command("route", "del", "-net", fields[0], "gw", gateway)
|
||||
err := delCmd.Run()
|
||||
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
|
||||
|
||||
@@ -133,9 +133,10 @@ func delRoutesByGateway(gateway string) error {
|
||||
cmd := exec.Command("route", "delete", fields[0], "mask", fields[1], gateway)
|
||||
err := cmd.Run()
|
||||
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
|
||||
|
||||
@@ -174,7 +174,7 @@ func (app *p2pApp) buildDirectTunnel() error {
|
||||
pn := GNetwork
|
||||
initErr := pn.requestPeerInfo(&app.config)
|
||||
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
|
||||
}
|
||||
t, err = pn.addDirectTunnel(app.config, 0)
|
||||
|
||||
@@ -115,6 +115,7 @@ func (pn *P2PNetwork) run() {
|
||||
pn.write(MsgHeartbeat, 0, "")
|
||||
case <-pn.restartCh:
|
||||
gLog.Printf(LvDEBUG, "got restart channel")
|
||||
pn.sdwan.reset()
|
||||
pn.online = false
|
||||
pn.wgReconnect.Wait() // wait read/autorunapp goroutine end
|
||||
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)
|
||||
}
|
||||
gConf.retryAllApp()
|
||||
|
||||
case t := <-pn.tunnelCloseCh:
|
||||
gLog.Printf(LvDEBUG, "got tunnelCloseCh %s", t.config.LogPeerNode())
|
||||
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,
|
||||
id: tid,
|
||||
writeData: make(chan []byte, WriteDataChanSize),
|
||||
@@ -533,7 +535,6 @@ func (pn *P2PNetwork) init() error {
|
||||
caCertPool, errCert := x509.SystemCertPool()
|
||||
if errCert != nil {
|
||||
gLog.Println(LvERROR, "Failed to load system root CAs:", errCert)
|
||||
} else {
|
||||
caCertPool = x509.NewCertPool()
|
||||
}
|
||||
caCertPool.AppendCertsFromPEM([]byte(rootCA))
|
||||
|
||||
@@ -19,13 +19,12 @@ const WriteDataChanSize int = 3000
|
||||
var buildTunnelMtx sync.Mutex
|
||||
|
||||
type P2PTunnel struct {
|
||||
pn *P2PNetwork
|
||||
conn underlay
|
||||
hbTime time.Time
|
||||
hbMtx sync.Mutex
|
||||
config AppConfig
|
||||
la *net.UDPAddr // local hole address
|
||||
ra *net.UDPAddr // remote hole address
|
||||
localHoleAddr *net.UDPAddr // local hole address
|
||||
remoteHoleAddr *net.UDPAddr // remote hole address
|
||||
overlayConns sync.Map // both TCP and UDP
|
||||
id uint64 // client side alloc rand.uint64 = server side
|
||||
running bool
|
||||
@@ -58,7 +57,7 @@ func (t *P2PTunnel) initPort() {
|
||||
t.coneLocalPort = localPort2
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -85,8 +84,8 @@ func (t *P2PTunnel) connect() error {
|
||||
if req.Token == 0 { // no relay token
|
||||
req.Token = gConf.Network.Token
|
||||
}
|
||||
t.pn.push(t.config.PeerNode, MsgPushConnectReq, req)
|
||||
head, body := t.pn.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, UnderlayConnectTimeout*3)
|
||||
GNetwork.push(t.config.PeerNode, MsgPushConnectReq, req)
|
||||
head, body := GNetwork.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, UnderlayConnectTimeout*3)
|
||||
if head == nil {
|
||||
return errors.New("connect error")
|
||||
}
|
||||
@@ -161,7 +160,7 @@ func (t *P2PTunnel) checkActive() bool {
|
||||
|
||||
// call when user delete tunnel
|
||||
func (t *P2PTunnel) close() {
|
||||
t.pn.NotifyTunnelClose(t)
|
||||
GNetwork.NotifyTunnelClose(t)
|
||||
if !t.running {
|
||||
return
|
||||
}
|
||||
@@ -169,7 +168,7 @@ func (t *P2PTunnel) close() {
|
||||
if t.conn != nil {
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -190,7 +189,7 @@ func (t *P2PTunnel) start() error {
|
||||
func (t *P2PTunnel) handshake() error {
|
||||
if t.config.peerConeNatPort > 0 { // only peer is cone should prepare t.ra
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@@ -198,7 +197,7 @@ func (t *P2PTunnel) handshake() error {
|
||||
if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 {
|
||||
gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion)
|
||||
} 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 {
|
||||
ts = PunchTsDelay
|
||||
}
|
||||
@@ -267,11 +266,11 @@ func (t *P2PTunnel) connectUnderlayUDP() (c underlay, err error) {
|
||||
}
|
||||
if t.config.isUnderlayServer == 1 {
|
||||
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" {
|
||||
ul, err = listenKCP(t.la.String(), TunnelIdleTimeout)
|
||||
ul, err = listenKCP(t.localHoleAddr.String(), TunnelIdleTimeout)
|
||||
} else {
|
||||
ul, err = listenQuic(t.la.String(), TunnelIdleTimeout)
|
||||
ul, err = listenQuic(t.localHoleAddr.String(), TunnelIdleTimeout)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -293,24 +292,24 @@ func (t *P2PTunnel) connectUnderlayUDP() (c underlay, err error) {
|
||||
}
|
||||
|
||||
//else
|
||||
conn, errL := net.ListenUDP("udp", t.la)
|
||||
conn, errL := net.ListenUDP("udp", t.localHoleAddr)
|
||||
if errL != nil {
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
conn, errL = net.ListenUDP("udp", t.la)
|
||||
conn, errL = net.ListenUDP("udp", t.localHoleAddr)
|
||||
if errL != nil {
|
||||
return nil, fmt.Errorf("%s listen error:%s", underlayProtocol, errL)
|
||||
}
|
||||
}
|
||||
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout)
|
||||
gLog.Printf(LvDEBUG, "%s dial to %s", underlayProtocol, t.ra.String())
|
||||
GNetwork.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, ReadMsgTimeout)
|
||||
gLog.Printf(LvDEBUG, "%s dial to %s", underlayProtocol, t.remoteHoleAddr.String())
|
||||
if t.config.UnderlayProtocol == "kcp" {
|
||||
ul, errL = dialKCP(conn, t.ra, TunnelIdleTimeout)
|
||||
ul, errL = dialKCP(conn, t.remoteHoleAddr, TunnelIdleTimeout)
|
||||
} else {
|
||||
ul, errL = dialQuic(conn, t.ra, TunnelIdleTimeout)
|
||||
ul, errL = dialQuic(conn, t.remoteHoleAddr, TunnelIdleTimeout)
|
||||
}
|
||||
|
||||
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()
|
||||
ul.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
||||
@@ -353,12 +352,12 @@ func (t *P2PTunnel) connectUnderlayTCP() (c underlay, err error) {
|
||||
|
||||
// client side
|
||||
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
|
||||
if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 {
|
||||
gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion)
|
||||
} 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 {
|
||||
ts = PunchTsDelay
|
||||
}
|
||||
@@ -394,7 +393,7 @@ func (t *P2PTunnel) connectUnderlayTCP() (c underlay, err error) {
|
||||
func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) {
|
||||
gLog.Printf(LvDEBUG, "connectUnderlayTCPSymmetric %s start ", 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 {
|
||||
ts = PunchTsDelay
|
||||
}
|
||||
@@ -426,7 +425,7 @@ func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) {
|
||||
}
|
||||
_, buff, err := ul.ReadBuffer()
|
||||
if err != nil {
|
||||
gLog.Printf(LvERROR, "utcp.ReadBuffer error:", err)
|
||||
gLog.Println(LvDEBUG, "c2s ul.ReadBuffer error:", err)
|
||||
return
|
||||
}
|
||||
req := P2PHandshakeReq{}
|
||||
@@ -455,7 +454,7 @@ func (t *P2PTunnel) connectUnderlayTCPSymmetric() (c underlay, err error) {
|
||||
|
||||
_, buff, err := ul.ReadBuffer()
|
||||
if err != nil {
|
||||
gLog.Printf(LvERROR, "utcp.ReadBuffer error:", err)
|
||||
gLog.Println(LvDEBUG, "s2c ul.ReadBuffer error:", err)
|
||||
return
|
||||
}
|
||||
req := P2PHandshakeReq{}
|
||||
@@ -490,7 +489,7 @@ func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
||||
defer gLog.Printf(LvDEBUG, "connectUnderlayTCP6 %s end ", t.config.LogPeerNode())
|
||||
var ul *underlayTCP6
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listen TCP6 error:%s", err)
|
||||
@@ -509,17 +508,17 @@ func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
||||
}
|
||||
|
||||
//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)
|
||||
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)
|
||||
}
|
||||
handshakeBegin := time.Now()
|
||||
ul.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
||||
_, buff, err := ul.ReadBuffer()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", err)
|
||||
_, buff, errR := ul.ReadBuffer()
|
||||
if errR != nil {
|
||||
return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", errR)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
@@ -596,7 +595,7 @@ func (t *P2PTunnel) readLoop() {
|
||||
}
|
||||
tunnelID := binary.LittleEndian.Uint64(body[:8])
|
||||
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)
|
||||
}
|
||||
case MsgRelayHeartbeat:
|
||||
@@ -608,7 +607,7 @@ func (t *P2PTunnel) readLoop() {
|
||||
// TODO: debug relay heartbeat
|
||||
gLog.Printf(LvDEBUG, "read MsgRelayHeartbeat from rtid:%d,appid:%d", req.RelayTunnelID, req.AppID)
|
||||
// update app hbtime
|
||||
t.pn.updateAppHeartbeat(req.AppID)
|
||||
GNetwork.updateAppHeartbeat(req.AppID)
|
||||
req.From = gConf.Network.Node
|
||||
t.WriteMessage(req.RelayTunnelID, MsgP2P, MsgRelayHeartbeatAck, &req)
|
||||
case MsgRelayHeartbeatAck:
|
||||
@@ -620,7 +619,7 @@ func (t *P2PTunnel) readLoop() {
|
||||
}
|
||||
// TODO: debug relay heartbeat
|
||||
gLog.Printf(LvDEBUG, "read MsgRelayHeartbeatAck to appid:%d", req.AppID)
|
||||
t.pn.updateAppHeartbeat(req.AppID)
|
||||
GNetwork.updateAppHeartbeat(req.AppID)
|
||||
case MsgOverlayConnectReq:
|
||||
req := OverlayConnectReq{}
|
||||
if err := json.Unmarshal(body, &req); err != nil {
|
||||
@@ -733,7 +732,7 @@ func (t *P2PTunnel) listen() error {
|
||||
FromIP: gConf.Network.publicIP,
|
||||
ConeNatPort: t.coneNatPort,
|
||||
ID: t.id,
|
||||
PunchTs: uint64(time.Now().UnixNano() + int64(PunchTsDelay) - t.pn.dt),
|
||||
PunchTs: uint64(time.Now().UnixNano() + int64(PunchTsDelay) - GNetwork.dt),
|
||||
Version: OpenP2PVersion,
|
||||
}
|
||||
t.punchTs = rsp.PunchTs
|
||||
@@ -742,7 +741,7 @@ func (t *P2PTunnel) listen() error {
|
||||
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")
|
||||
t.tunnelServer = true
|
||||
return t.start()
|
||||
@@ -760,9 +759,9 @@ func (t *P2PTunnel) closeOverlayConns(appID uint64) {
|
||||
|
||||
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)
|
||||
ch := t.pn.nodeData
|
||||
ch := GNetwork.nodeData
|
||||
// if body[9] == 1 { // TODO: deal relay
|
||||
// ch = t.pn.nodeDataSmall
|
||||
// ch = GNetwork.nodeDataSmall
|
||||
// gLog.Printf(LvDEBUG, "read icmp %d", time.Now().Unix())
|
||||
// }
|
||||
if isRelay {
|
||||
|
||||
87
core/ping.go
Normal file
87
core/ping.go
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const OpenP2PVersion = "3.19.0"
|
||||
const OpenP2PVersion = "3.21.12"
|
||||
const ProductName string = "openp2p"
|
||||
const LeastSupportVersion = "3.0.0"
|
||||
const SyncServerTimeVersion = "3.9.0"
|
||||
@@ -167,7 +167,7 @@ const (
|
||||
MaxRetry = 10
|
||||
Cone2ConeTCPPunchMaxRetry = 1
|
||||
Cone2ConeUDPPunchMaxRetry = 1
|
||||
PublicIPEchoTimeout = time.Second * 1
|
||||
PublicIPEchoTimeout = time.Second * 3
|
||||
NatTestTimeout = time.Second * 5
|
||||
UDPReadTimeout = time.Second * 5
|
||||
ClientAPITimeout = time.Second * 10
|
||||
@@ -217,6 +217,12 @@ const (
|
||||
MsgSDWANInfoRsp
|
||||
)
|
||||
|
||||
// MsgNATDetect
|
||||
const (
|
||||
MsgNAT = iota
|
||||
MsgPublicIP
|
||||
)
|
||||
|
||||
func newMessage(mainType uint16, subType uint16, packet interface{}) ([]byte, error) {
|
||||
data, err := json.Marshal(packet)
|
||||
if err != nil {
|
||||
@@ -495,7 +501,7 @@ type SDWANInfo struct {
|
||||
ForceRelay int32 `json:"forceRelay,omitempty"`
|
||||
PunchPriority int32 `json:"punchPriority,omitempty"`
|
||||
Enable int32 `json:"enable,omitempty"`
|
||||
Nodes []SDWANNode
|
||||
Nodes []*SDWANNode
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -52,18 +52,36 @@ type p2pSDWAN struct {
|
||||
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 {
|
||||
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 {
|
||||
s.internalRoute = NewIPTree("")
|
||||
}
|
||||
|
||||
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() {
|
||||
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())
|
||||
s.internalRoute.Del(node.IP, node.IP)
|
||||
ipNum, _ := inetAtoN(node.IP)
|
||||
@@ -88,24 +106,26 @@ func (s *p2pSDWAN) init(name string) error {
|
||||
}
|
||||
s.internalRoute.Del(minIP.String(), maxIP.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() {
|
||||
gLog.Println(LvDEBUG, "deal add node: ", node.Name)
|
||||
gLog.Println(LvDEBUG, "sdwan init: deal add node: ", node.Name)
|
||||
ipNet := &net.IPNet{
|
||||
IP: net.ParseIP(node.IP),
|
||||
Mask: s.subnet.Mask,
|
||||
}
|
||||
if node.Name == s.nodeName {
|
||||
s.virtualIP = ipNet
|
||||
gLog.Println(LvINFO, "start tun ", ipNet.String())
|
||||
gLog.Println(LvINFO, "sdwan init: start tun ", ipNet.String())
|
||||
err := s.StartTun()
|
||||
if err != nil {
|
||||
gLog.Println(LvERROR, "start tun error:", err)
|
||||
gLog.Println(LvERROR, "sdwan init: start tun error:", err)
|
||||
return err
|
||||
}
|
||||
gLog.Println(LvINFO, "start tun ok")
|
||||
gLog.Println(LvINFO, "sdwan init: start tun ok")
|
||||
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("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
|
||||
@@ -124,18 +144,28 @@ func (s *p2pSDWAN) init(name string) error {
|
||||
continue
|
||||
}
|
||||
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, ",")
|
||||
for _, r := range arr {
|
||||
// add internal route
|
||||
_, ipnet, err := net.ParseCIDR(r)
|
||||
if err != nil {
|
||||
fmt.Println("Error parsing CIDR:", err)
|
||||
fmt.Println("sdwan init: Error parsing CIDR:", err)
|
||||
continue
|
||||
}
|
||||
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
|
||||
}
|
||||
// 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
|
||||
maxIP := make(net.IP, len(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)})
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func DefaultReadBuffer(ul underlay) (*openP2PHeader, []byte, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
head, err := decodeHeader(headBuf)
|
||||
if err != nil {
|
||||
if err != nil || head.MainType > 16 {
|
||||
return nil, nil, err
|
||||
}
|
||||
dataBuf := make([]byte, head.DataLen)
|
||||
|
||||
@@ -51,7 +51,7 @@ func listenTCP(host string, port int, localPort int, mode string, t *P2PTunnel)
|
||||
if compareVersion(t.config.peerVersion, SyncServerTimeVersion) < 0 {
|
||||
gLog.Printf(LvDEBUG, "peer version %s less than %s", t.config.peerVersion, SyncServerTimeVersion)
|
||||
} 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)
|
||||
time.Sleep(ts)
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func listenTCP(host string, port int, localPort int, mode string, t *P2PTunnel)
|
||||
utcp.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, buff)
|
||||
return utcp, nil
|
||||
}
|
||||
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
||||
GNetwork.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
||||
tid := t.id
|
||||
if compareVersion(t.config.peerVersion, PublicIPVersion) < 0 { // old version
|
||||
ipBytes := net.ParseIP(t.config.peerIP).To4()
|
||||
|
||||
@@ -47,7 +47,7 @@ func (vl *v4Listener) handleConnection(c net.Conn) {
|
||||
utcp.SetReadDeadline(time.Now().Add(UnderlayTCPConnectTimeout))
|
||||
_, buff, err := utcp.ReadBuffer()
|
||||
if err != nil {
|
||||
gLog.Printf(LvERROR, "utcp.ReadBuffer error:", err)
|
||||
gLog.Println(LvERROR, "utcp.ReadBuffer error:", err)
|
||||
}
|
||||
utcp.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, buff)
|
||||
var tid uint64
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 23 KiB |
23
go.mod
23
go.mod
@@ -8,17 +8,16 @@ require (
|
||||
github.com/openp2p-cn/go-reuseport v0.3.2
|
||||
github.com/openp2p-cn/service v1.0.0
|
||||
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/vishvananda/netlink v1.1.0
|
||||
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54
|
||||
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
|
||||
)
|
||||
|
||||
require (
|
||||
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/kardianos/service v1.2.2 // 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/xorsimd v0.4.2 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/net v0.26.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // 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.28.1 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gvisor.dev/gvisor v0.0.0-20241128011400-745828301c93 // indirect
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user