mirror of
https://github.com/openp2p-cn/openp2p.git
synced 2026-05-11 00:48:22 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
532d3667ce |
@@ -23,7 +23,7 @@
|
|||||||
### 5. 跨平台
|
### 5. 跨平台
|
||||||
因为轻量,所以很容易支持各个平台。支持主流的操作系统:Windows,Linux,MacOS;和主流的cpu架构:386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64
|
因为轻量,所以很容易支持各个平台。支持主流的操作系统:Windows,Linux,MacOS;和主流的cpu架构:386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64
|
||||||
### 6. 高效
|
### 6. 高效
|
||||||
P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络环境,无论NAT1-4(Cone或Symmetric),都支持。依靠Quic协议优秀的拥塞算法,能在糟糕的网络环境获得高带宽低延时。
|
P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络环境,无论NAT1-4(Cone或Symmetric),UPNP,IPv6都支持。依靠Quic协议优秀的拥塞算法,能在糟糕的网络环境获得高带宽低延时。
|
||||||
|
|
||||||
### 7. 二次开发
|
### 7. 二次开发
|
||||||
基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信
|
基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信
|
||||||
@@ -105,7 +105,7 @@ go build
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
近期计划:
|
近期计划:
|
||||||
1. 支持IPv6
|
1. 支持IPv6(100%)
|
||||||
2. 支持随系统自动启动,安装成系统服务(100%)
|
2. 支持随系统自动启动,安装成系统服务(100%)
|
||||||
3. 提供一些免费服务器给特别差的网络,如广电网络(100%)
|
3. 提供一些免费服务器给特别差的网络,如广电网络(100%)
|
||||||
4. 建立网站,用户可以在网站管理所有P2PApp和设备。查看设备在线状态,升级,增删查改重启P2PApp等(100%)
|
4. 建立网站,用户可以在网站管理所有P2PApp和设备。查看设备在线状态,升级,增删查改重启P2PApp等(100%)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ The code is open source, the P2P tunnel uses TLS1.3+AES double encryption, and t
|
|||||||
Benefit from lightweight, it easily supports most of major OS, like Windows, Linux, MacOS, also most of CPU architecture, like 386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64.
|
Benefit from lightweight, it easily supports most of major OS, like Windows, Linux, MacOS, also most of CPU architecture, like 386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64.
|
||||||
|
|
||||||
### 6. Efficient
|
### 6. Efficient
|
||||||
P2P direct connection lets your devices make good use of bandwidth. Your device can be connected in any network environments, even supports NAT1-4 (Cone or Symmetric). Relying on the excellent congestion algorithm of the Quic protocol, high bandwidth and low latency can be obtained in a bad network environment.
|
P2P direct connection lets your devices make good use of bandwidth. Your device can be connected in any network environments, even supports NAT1-4 (Cone or Symmetric),UPNP,IPv6. Relying on the excellent congestion algorithm of the Quic protocol, high bandwidth and low latency can be obtained in a bad network environment.
|
||||||
|
|
||||||
### 7. Integration
|
### 7. Integration
|
||||||
Your applicaiton can call OpenP2P with a few code to make any internal networks communicate with each other.
|
Your applicaiton can call OpenP2P with a few code to make any internal networks communicate with each other.
|
||||||
@@ -113,7 +113,7 @@ go build
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
Short-Term:
|
Short-Term:
|
||||||
1. Support IPv6.
|
1. Support IPv6.(100%)
|
||||||
2. Support auto run when system boot, setup system service.(100%)
|
2. Support auto run when system boot, setup system service.(100%)
|
||||||
3. Provide free servers to some low-performance network.(100%)
|
3. Provide free servers to some low-performance network.(100%)
|
||||||
4. Build website, users can manage all P2PApp and devices via it. View devices' online status, upgrade, restart or CURD P2PApp .(100%)
|
4. Build website, users can manage all P2PApp and devices via it. View devices' online status, upgrade, restart or CURD P2PApp .(100%)
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ nohup ./openp2p -d -node OFFICEPC1 -token TOKEN &
|
|||||||
# update local client
|
# update local client
|
||||||
./openp2p update
|
./openp2p update
|
||||||
# update remote client
|
# update remote client
|
||||||
curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password='
|
curl --insecure 'https://api.openp2p.cn:27183/api/v1/device/YOUR-NODE-NAME/update?user=&password='
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows系统需要设置防火墙放行本程序,程序会自动设置,如果设置失败会影响连接功能。
|
Windows系统需要设置防火墙放行本程序,程序会自动设置,如果设置失败会影响连接功能。
|
||||||
|
|||||||
2
USAGE.md
2
USAGE.md
@@ -79,7 +79,7 @@ Configuration example
|
|||||||
# update local client
|
# update local client
|
||||||
./openp2p update
|
./openp2p update
|
||||||
# update remote client
|
# update remote client
|
||||||
curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password='
|
curl --insecure 'https://api.openp2p.cn:27183/api/v1/device/YOUR-NODE-NAME/update?user=&password='
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows system needs to set up firewall for this program, the program will automatically set the firewall, if the setting fails, the UDP punching will be affected.
|
Windows system needs to set up firewall for this program, the program will automatically set the firewall, if the setting fails, the UDP punching will be affected.
|
||||||
|
|||||||
12
config.go
12
config.go
@@ -38,6 +38,7 @@ type AppConfig struct {
|
|||||||
shareBandwidth int
|
shareBandwidth int
|
||||||
errMsg string
|
errMsg string
|
||||||
connectTime time.Time
|
connectTime time.Time
|
||||||
|
fromToken uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add loglevel, maxlogfilesize
|
// TODO: add loglevel, maxlogfilesize
|
||||||
@@ -148,7 +149,6 @@ type NetworkConfig struct {
|
|||||||
Node string
|
Node string
|
||||||
User string
|
User string
|
||||||
localIP string
|
localIP string
|
||||||
ipv6 string
|
|
||||||
mac string
|
mac string
|
||||||
os string
|
os string
|
||||||
publicIP string
|
publicIP string
|
||||||
@@ -253,3 +253,13 @@ func parseParams(subCommand string) {
|
|||||||
// gConf.mtx.Unlock()
|
// gConf.mtx.Unlock()
|
||||||
gConf.save()
|
gConf.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (conf *AppConfig) isSupportTCP(pnConf NetworkConfig) bool {
|
||||||
|
if conf.peerVersion == "" || compareVersion(conf.peerVersion, LeastSupportTCPVersion) == LESS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if pnConf.hasIPv4 == 1 || pnConf.hasUPNPorNATPMP == 1 || conf.hasIPv4 == 1 || conf.hasUPNPorNATPMP == 1 || (IsIPv6(pnConf.IPv6) && IsIPv6(conf.IPv6)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
gLog.Println(LvDEBUG, "push connect response to ", req.From)
|
gLog.Println(LvDEBUG, "push connect response to ", req.From)
|
||||||
// verify totp token or token
|
// verify totp token or token
|
||||||
if VerifyTOTP(req.Token, pn.config.Token, time.Now().Unix()+(pn.serverTs-pn.localTs)) || // localTs may behind, auto adjust ts
|
if VerifyTOTP(req.Token, pn.config.Token, time.Now().Unix()+(pn.serverTs-pn.localTs)) || // localTs may behind, auto adjust ts
|
||||||
VerifyTOTP(req.Token, pn.config.Token, time.Now().Unix()) ||
|
VerifyTOTP(req.Token, pn.config.Token, time.Now().Unix()) {
|
||||||
(req.FromToken == pn.config.Token) {
|
|
||||||
gLog.Printf(LvINFO, "Access Granted\n")
|
gLog.Printf(LvINFO, "Access Granted\n")
|
||||||
config := AppConfig{}
|
config := AppConfig{}
|
||||||
config.peerNatType = req.NatType
|
config.peerNatType = req.NatType
|
||||||
@@ -39,8 +38,10 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
config.peerIP = req.FromIP
|
config.peerIP = req.FromIP
|
||||||
config.PeerNode = req.From
|
config.PeerNode = req.From
|
||||||
config.peerVersion = req.Version
|
config.peerVersion = req.Version
|
||||||
|
config.fromToken = req.Token
|
||||||
|
config.IPv6 = req.IPv6
|
||||||
// share relay node will limit bandwidth
|
// share relay node will limit bandwidth
|
||||||
if req.FromToken != pn.config.Token {
|
if req.Token != pn.config.Token {
|
||||||
gLog.Printf(LvINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
|
gLog.Printf(LvINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
|
||||||
config.shareBandwidth = pn.config.ShareBandwidth
|
config.shareBandwidth = pn.config.ShareBandwidth
|
||||||
}
|
}
|
||||||
@@ -124,6 +125,7 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
appActive := 0
|
appActive := 0
|
||||||
relayNode := ""
|
relayNode := ""
|
||||||
relayMode := ""
|
relayMode := ""
|
||||||
|
linkMode := LinkModeUDPPunch
|
||||||
i, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
|
i, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
|
||||||
if ok {
|
if ok {
|
||||||
app := i.(*p2pApp)
|
app := i.(*p2pApp)
|
||||||
@@ -132,6 +134,7 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
}
|
}
|
||||||
relayNode = app.relayNode
|
relayNode = app.relayNode
|
||||||
relayMode = app.relayMode
|
relayMode = app.relayMode
|
||||||
|
linkMode = app.tunnel.linkMode
|
||||||
}
|
}
|
||||||
appInfo := AppInfo{
|
appInfo := AppInfo{
|
||||||
AppName: config.AppName,
|
AppName: config.AppName,
|
||||||
@@ -140,6 +143,7 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
SrcPort: config.SrcPort,
|
SrcPort: config.SrcPort,
|
||||||
RelayNode: relayNode,
|
RelayNode: relayNode,
|
||||||
RelayMode: relayMode,
|
RelayMode: relayMode,
|
||||||
|
LinkMode: linkMode,
|
||||||
PeerNode: config.PeerNode,
|
PeerNode: config.PeerNode,
|
||||||
DstHost: config.DstHost,
|
DstHost: config.DstHost,
|
||||||
DstPort: config.DstPort,
|
DstPort: config.DstPort,
|
||||||
|
|||||||
22
nat.go
22
nat.go
@@ -96,33 +96,29 @@ func natTest(serverHost string, serverPort int, localPort int, echoPort int) (pu
|
|||||||
return natRsp.IP, hasPublicIP, hasUPNPorNATPMP, natRsp.Port, nil
|
return natRsp.IP, hasPublicIP, hasUPNPorNATPMP, natRsp.Port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, hasUPNPorNATPMP int, err error) {
|
func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, hasIPvr int, hasUPNPorNATPMP int, err error) {
|
||||||
// the random local port may be used by other.
|
// the random local port may be used by other.
|
||||||
localPort := int(rand.Uint32()%10000 + 50000)
|
localPort := int(rand.Uint32()%10000 + 50000)
|
||||||
echoPort := int(rand.Uint32()%10000 + 50000)
|
echoPort := int(rand.Uint32()%10000 + 50000)
|
||||||
go echo(echoPort)
|
go echo(echoPort)
|
||||||
ip1, hasPublicIP, hasUPNPorNATPMP, port1, err := natTest(host, udp1, localPort, echoPort)
|
ip1, hasIPv4, hasUPNPorNATPMP, port1, err := natTest(host, udp1, localPort, echoPort)
|
||||||
gLog.Printf(LvDEBUG, "local port:%d nat port:%d", localPort, port1)
|
gLog.Printf(LvDEBUG, "local port:%d nat port:%d", localPort, port1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, hasUPNPorNATPMP, err
|
return "", 0, hasIPv4, hasUPNPorNATPMP, err
|
||||||
}
|
}
|
||||||
if hasPublicIP == 1 || hasUPNPorNATPMP == 1 {
|
// if hasPublicIP == 1 || hasUPNPorNATPMP == 1 {
|
||||||
return ip1, NATNone, hasUPNPorNATPMP, nil
|
// return ip1, NATNone, hasUPNPorNATPMP, nil
|
||||||
}
|
// }
|
||||||
ip2, _, _, port2, err := natTest(host, udp2, localPort, 0) // 2rd nat test not need testing publicip
|
_, _, _, port2, err := natTest(host, udp2, localPort, 0) // 2rd nat test not need testing publicip
|
||||||
gLog.Printf(LvDEBUG, "local port:%d nat port:%d", localPort, port2)
|
gLog.Printf(LvDEBUG, "local port:%d nat port:%d", localPort, port2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, hasUPNPorNATPMP, err
|
return "", 0, hasIPv4, hasUPNPorNATPMP, err
|
||||||
}
|
|
||||||
if ip1 != ip2 {
|
|
||||||
return "", 0, hasUPNPorNATPMP, fmt.Errorf("ip have changed, please retry again")
|
|
||||||
}
|
}
|
||||||
natType := NATSymmetric
|
natType := NATSymmetric
|
||||||
if port1 == port2 {
|
if port1 == port2 {
|
||||||
natType = NATCone
|
natType = NATCone
|
||||||
}
|
}
|
||||||
//TODO: NATNone
|
return ip1, natType, hasIPv4, hasUPNPorNATPMP, nil
|
||||||
return ip1, natType, hasUPNPorNATPMP, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func echo(echoPort int) {
|
func echo(echoPort int) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -236,6 +237,14 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
|||||||
peerNatType = t.config.peerNatType
|
peerNatType = t.config.peerNatType
|
||||||
peerIP = t.config.peerIP
|
peerIP = t.config.peerIP
|
||||||
}
|
}
|
||||||
|
// TODO: if tcp failed, should try udp punching, nattype should refactor also, when NATNONE and failed we don't know the peerNatType
|
||||||
|
// if err != nil && err == ErrorHandshake && t.isSupportTCP() {
|
||||||
|
// t, err = pn.addDirectTunnel(config, 0)
|
||||||
|
// if t != nil {
|
||||||
|
// peerNatType = t.config.peerNatType
|
||||||
|
// peerIP = t.config.peerIP
|
||||||
|
// }
|
||||||
|
// }
|
||||||
if err != nil && err == ErrorHandshake {
|
if err != nil && err == ErrorHandshake {
|
||||||
gLog.Println(LvERROR, "direct connect failed, try to relay")
|
gLog.Println(LvERROR, "direct connect failed, try to relay")
|
||||||
t, rtid, relayMode, err = pn.addRelayTunnel(config)
|
t, rtid, relayMode, err = pn.addRelayTunnel(config)
|
||||||
@@ -373,13 +382,18 @@ func (pn *P2PNetwork) init() error {
|
|||||||
var err error
|
var err error
|
||||||
for {
|
for {
|
||||||
// detect nat type
|
// detect nat type
|
||||||
pn.config.publicIP, pn.config.natType, pn.config.hasUPNPorNATPMP, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2)
|
pn.config.publicIP, pn.config.natType, pn.config.hasIPv4, pn.config.hasUPNPorNATPMP, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2)
|
||||||
// for testcase
|
// for testcase
|
||||||
if strings.Contains(pn.config.Node, "openp2pS2STest") {
|
if strings.Contains(pn.config.Node, "openp2pS2STest") {
|
||||||
pn.config.natType = NATSymmetric
|
pn.config.natType = NATSymmetric
|
||||||
|
pn.config.hasIPv4 = 0
|
||||||
|
pn.config.hasUPNPorNATPMP = 0
|
||||||
|
|
||||||
}
|
}
|
||||||
if strings.Contains(pn.config.Node, "openp2pC2CTest") {
|
if strings.Contains(pn.config.Node, "openp2pC2CTest") {
|
||||||
pn.config.natType = NATCone
|
pn.config.natType = NATCone
|
||||||
|
pn.config.hasIPv4 = 0
|
||||||
|
pn.config.hasUPNPorNATPMP = 0
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvDEBUG, "detect NAT type error:", err)
|
gLog.Println(LvDEBUG, "detect NAT type error:", err)
|
||||||
@@ -429,7 +443,7 @@ func (pn *P2PNetwork) init() error {
|
|||||||
gLog.Println(LvDEBUG, "netinfo:", rsp)
|
gLog.Println(LvDEBUG, "netinfo:", rsp)
|
||||||
if rsp != nil && rsp.Country != "" {
|
if rsp != nil && rsp.Country != "" {
|
||||||
if IsIPv6(rsp.IP.String()) {
|
if IsIPv6(rsp.IP.String()) {
|
||||||
pn.config.ipv6 = rsp.IP.String()
|
pn.config.IPv6 = rsp.IP.String()
|
||||||
req.IPv6 = rsp.IP.String()
|
req.IPv6 = rsp.IP.String()
|
||||||
}
|
}
|
||||||
req.NetInfo = *rsp
|
req.NetInfo = *rsp
|
||||||
@@ -611,3 +625,23 @@ func (pn *P2PNetwork) updateAppHeartbeat(appID uint64) {
|
|||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pn *P2PNetwork) refreshIPv6() {
|
||||||
|
if !IsIPv6(pn.config.IPv6) { // not support ipv6, not refresh
|
||||||
|
return
|
||||||
|
}
|
||||||
|
client := &http.Client{Timeout: time.Second * 10}
|
||||||
|
r, err := client.Get("http://6.ipw.cn")
|
||||||
|
if err != nil {
|
||||||
|
gLog.Println(LvINFO, "refreshIPv6 error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer r.Body.Close()
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
n, err := r.Body.Read(buf)
|
||||||
|
if n <= 0 {
|
||||||
|
gLog.Println(LvINFO, "netInfo error:", err, n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pn.config.IPv6 = string(buf[:n])
|
||||||
|
}
|
||||||
|
|||||||
88
p2ptunnel.go
88
p2ptunnel.go
@@ -28,6 +28,7 @@ type P2PTunnel struct {
|
|||||||
tunnelServer bool // different from underlayServer
|
tunnelServer bool // different from underlayServer
|
||||||
coneLocalPort int
|
coneLocalPort int
|
||||||
coneNatPort int
|
coneNatPort int
|
||||||
|
linkMode string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *P2PTunnel) init() {
|
func (t *P2PTunnel) init() {
|
||||||
@@ -65,11 +66,11 @@ func (t *P2PTunnel) init() {
|
|||||||
func (t *P2PTunnel) connect() error {
|
func (t *P2PTunnel) connect() error {
|
||||||
gLog.Printf(LvDEBUG, "start p2pTunnel to %s ", t.config.PeerNode)
|
gLog.Printf(LvDEBUG, "start p2pTunnel to %s ", t.config.PeerNode)
|
||||||
t.tunnelServer = false
|
t.tunnelServer = false
|
||||||
|
t.pn.refreshIPv6()
|
||||||
appKey := uint64(0)
|
appKey := uint64(0)
|
||||||
req := PushConnectReq{
|
req := PushConnectReq{
|
||||||
Token: t.config.peerToken,
|
Token: t.config.peerToken,
|
||||||
From: t.pn.config.Node,
|
From: t.pn.config.Node,
|
||||||
FromToken: t.pn.config.Token,
|
|
||||||
FromIP: t.pn.config.publicIP,
|
FromIP: t.pn.config.publicIP,
|
||||||
ConeNatPort: t.coneNatPort,
|
ConeNatPort: t.coneNatPort,
|
||||||
NatType: t.pn.config.natType,
|
NatType: t.pn.config.natType,
|
||||||
@@ -80,6 +81,9 @@ func (t *P2PTunnel) connect() error {
|
|||||||
AppKey: appKey,
|
AppKey: appKey,
|
||||||
Version: OpenP2PVersion,
|
Version: OpenP2PVersion,
|
||||||
}
|
}
|
||||||
|
if req.Token == 0 { // no relay token
|
||||||
|
req.Token = t.pn.config.Token
|
||||||
|
}
|
||||||
t.pn.push(t.config.PeerNode, MsgPushConnectReq, req)
|
t.pn.push(t.config.PeerNode, MsgPushConnectReq, req)
|
||||||
head, body := t.pn.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, time.Second*10)
|
head, body := t.pn.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, time.Second*10)
|
||||||
if head == nil {
|
if head == nil {
|
||||||
@@ -158,7 +162,7 @@ func (t *P2PTunnel) close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *P2PTunnel) start() error {
|
func (t *P2PTunnel) start() error {
|
||||||
if !t.isSupportTCP() {
|
if !t.config.isSupportTCP(t.pn.config) {
|
||||||
if err := t.handshake(); err != nil {
|
if err := t.handshake(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -182,7 +186,7 @@ func (t *P2PTunnel) handshake() error {
|
|||||||
gLog.Println(LvDEBUG, "handshake to ", t.config.PeerNode)
|
gLog.Println(LvDEBUG, "handshake to ", t.config.PeerNode)
|
||||||
var err error
|
var err error
|
||||||
// TODO: handle NATNone, nodes with public ip has no punching
|
// TODO: handle NATNone, nodes with public ip has no punching
|
||||||
if (t.pn.config.natType == NATCone && t.config.peerNatType == NATCone) || (t.pn.config.natType == NATNone || t.config.peerNatType == NATNone) {
|
if t.pn.config.natType == NATCone && t.config.peerNatType == NATCone {
|
||||||
err = handshakeC2C(t)
|
err = handshakeC2C(t)
|
||||||
} else if t.config.peerNatType == NATSymmetric && t.pn.config.natType == NATSymmetric {
|
} else if t.config.peerNatType == NATSymmetric && t.pn.config.natType == NATSymmetric {
|
||||||
err = ErrorS2S
|
err = ErrorS2S
|
||||||
@@ -203,28 +207,23 @@ func (t *P2PTunnel) handshake() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *P2PTunnel) connectUnderlay() (err error) {
|
func (t *P2PTunnel) connectUnderlay() (err error) {
|
||||||
if !t.isSupportTCP() {
|
if !t.config.isSupportTCP(t.pn.config) {
|
||||||
t.conn, err = t.connectUnderlayQuic()
|
t.conn, err = t.connectUnderlayQuic()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: udp or tcp first?
|
if IsIPv6(t.pn.config.IPv6) && IsIPv6(t.config.IPv6) { // both have ipv6
|
||||||
// prepare a la ra for udp
|
t.conn, err = t.connectUnderlayTCP6()
|
||||||
// t.conn, err = t.connectUnderlayQuic()
|
if err != nil {
|
||||||
// TODO: support ipv6
|
return err
|
||||||
// if t.pn.config.hasIPv4 == 1 || t.config.hasIPv4 == 1 {
|
}
|
||||||
t.conn, err = t.connectUnderlayTCP()
|
} else { // hasipv4 or upnp
|
||||||
if err != nil {
|
t.conn, err = t.connectUnderlayTCP()
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
// if IsIPv6(t.pn.config.IPv6) && IsIPv6(t.config.IPv6) { // both have ipv6
|
|
||||||
// t.conn, err = t.connectUnderlayTCP6()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
t.setRun(true)
|
t.setRun(true)
|
||||||
go t.readLoop()
|
go t.readLoop()
|
||||||
@@ -289,6 +288,7 @@ func (t *P2PTunnel) connectUnderlayQuic() (c underlay, err error) {
|
|||||||
|
|
||||||
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
||||||
gLog.Println(LvDEBUG, "quic connection ok")
|
gLog.Println(LvDEBUG, "quic connection ok")
|
||||||
|
t.linkMode = LinkModeUDPPunch
|
||||||
return qConn, nil
|
return qConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,18 +336,19 @@ func (t *P2PTunnel) connectUnderlayTCP() (c underlay, err error) {
|
|||||||
|
|
||||||
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
||||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
gLog.Println(LvDEBUG, "TCP connection ok")
|
||||||
|
t.linkMode = LinkModeIPv4
|
||||||
return qConn, nil
|
return qConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
||||||
gLog.Println(LvINFO, "connectUnderlayTCP start")
|
gLog.Println(LvINFO, "connectUnderlayTCP6 start")
|
||||||
defer gLog.Println(LvINFO, "connectUnderlayTCP end")
|
defer gLog.Println(LvINFO, "connectUnderlayTCP6 end")
|
||||||
var qConn *underlayTCP6
|
var qConn *underlayTCP6
|
||||||
if t.isUnderlayServer() {
|
if t.isUnderlayServer() {
|
||||||
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
||||||
qConn, err = listenTCP6(t.coneNatPort, TunnelIdleTimeout)
|
qConn, err = listenTCP6(t.coneNatPort, TunnelIdleTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("listen TCP error:%s", err)
|
return nil, fmt.Errorf("listen TCP6 error:%s", err)
|
||||||
}
|
}
|
||||||
_, buff, err := qConn.ReadBuffer()
|
_, buff, err := qConn.ReadBuffer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -358,16 +359,16 @@ func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
|||||||
gLog.Println(LvDEBUG, string(buff))
|
gLog.Println(LvDEBUG, string(buff))
|
||||||
}
|
}
|
||||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, []byte("OpenP2P,hello2"))
|
qConn.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, []byte("OpenP2P,hello2"))
|
||||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
gLog.Println(LvDEBUG, "TCP6 connection ok")
|
||||||
return qConn, nil
|
return qConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//else
|
//else
|
||||||
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, time.Second*5)
|
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, time.Second*5)
|
||||||
gLog.Println(LvDEBUG, "TCP dial to ", t.ra.String())
|
gLog.Println(LvDEBUG, "TCP6 dial to ", t.config.IPv6)
|
||||||
qConn, err = dialTCP6(t.config.IPv6, t.config.peerConeNatPort)
|
qConn, err = dialTCP6(t.config.IPv6, t.config.peerConeNatPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("TCP dial to %s error:%s", t.ra.String(), err)
|
return nil, fmt.Errorf("TCP6 dial to %s:%d error:%s", t.config.IPv6, t.config.peerConeNatPort, err)
|
||||||
}
|
}
|
||||||
handshakeBegin := time.Now()
|
handshakeBegin := time.Now()
|
||||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
qConn.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
||||||
@@ -381,7 +382,8 @@ func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
||||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
gLog.Println(LvDEBUG, "TCP6 connection ok")
|
||||||
|
t.linkMode = LinkModeIPv6
|
||||||
return qConn, nil
|
return qConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,19 +553,25 @@ func (t *P2PTunnel) heartbeatLoop() {
|
|||||||
func (t *P2PTunnel) listen() error {
|
func (t *P2PTunnel) listen() error {
|
||||||
// notify client to connect
|
// notify client to connect
|
||||||
rsp := PushConnectRsp{
|
rsp := PushConnectRsp{
|
||||||
Error: 0,
|
Error: 0,
|
||||||
Detail: "connect ok",
|
Detail: "connect ok",
|
||||||
To: t.config.PeerNode,
|
To: t.config.PeerNode,
|
||||||
From: t.pn.config.Node,
|
From: t.pn.config.Node,
|
||||||
NatType: t.pn.config.natType,
|
NatType: t.pn.config.natType,
|
||||||
HasIPv4: t.pn.config.hasIPv4,
|
HasIPv4: t.pn.config.hasIPv4,
|
||||||
IPv6: t.pn.config.IPv6,
|
// IPv6: t.pn.config.IPv6,
|
||||||
HasUPNPorNATPMP: t.pn.config.hasUPNPorNATPMP,
|
HasUPNPorNATPMP: t.pn.config.hasUPNPorNATPMP,
|
||||||
FromIP: t.pn.config.publicIP,
|
FromIP: t.pn.config.publicIP,
|
||||||
ConeNatPort: t.coneNatPort,
|
ConeNatPort: t.coneNatPort,
|
||||||
ID: t.id,
|
ID: t.id,
|
||||||
Version: OpenP2PVersion,
|
Version: OpenP2PVersion,
|
||||||
}
|
}
|
||||||
|
// only private node set ipv6
|
||||||
|
if t.config.fromToken == t.pn.config.Token {
|
||||||
|
t.pn.refreshIPv6()
|
||||||
|
rsp.IPv6 = t.pn.config.IPv6
|
||||||
|
}
|
||||||
|
|
||||||
t.pn.push(t.config.PeerNode, MsgPushConnectRsp, rsp)
|
t.pn.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
|
||||||
@@ -588,22 +596,12 @@ func (t *P2PTunnel) closeOverlayConns(appID uint64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *P2PTunnel) isUnderlayServer() bool {
|
func (t *P2PTunnel) isUnderlayServer() bool {
|
||||||
if t.pn.config.natType == NATNone && t.config.peerNatType != NATNone {
|
if (t.pn.config.hasIPv4 == 1 || t.pn.config.hasUPNPorNATPMP == 1) && (t.config.hasIPv4 != 1 || t.config.hasUPNPorNATPMP != 1) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if t.pn.config.natType != NATNone && t.config.peerNatType == NATNone {
|
if (t.pn.config.hasIPv4 != 1 || t.pn.config.hasUPNPorNATPMP != 1) && (t.config.hasIPv4 == 1 || t.config.hasUPNPorNATPMP == 1) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// NAT or both has public IP
|
// NAT or both has public IP
|
||||||
return t.tunnelServer
|
return t.tunnelServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *P2PTunnel) isSupportTCP() bool {
|
|
||||||
if t.config.peerVersion == "" || compareVersion(t.config.peerVersion, LeastSupportTCPVersion) == LESS {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if t.pn.config.natType == NATNone || t.config.peerNatType == NATNone {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
16
protocol.go
16
protocol.go
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const OpenP2PVersion = "1.5.6"
|
const OpenP2PVersion = "2.0.1"
|
||||||
const ProducnName string = "openp2p"
|
const ProducnName string = "openp2p"
|
||||||
const LeastSupportTCPVersion = "1.5.0"
|
const LeastSupportTCPVersion = "1.5.0"
|
||||||
|
|
||||||
@@ -155,6 +155,13 @@ const (
|
|||||||
UderlayTCP = "tcp"
|
UderlayTCP = "tcp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// linkmode
|
||||||
|
const (
|
||||||
|
LinkModeUDPPunch = "udppunch"
|
||||||
|
LinkModeIPv4 = "ipv4"
|
||||||
|
LinkModeIPv6 = "ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
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 {
|
||||||
@@ -181,9 +188,9 @@ func nodeNameToID(name string) uint64 {
|
|||||||
|
|
||||||
type PushConnectReq struct {
|
type PushConnectReq struct {
|
||||||
From string `json:"from,omitempty"`
|
From string `json:"from,omitempty"`
|
||||||
FromToken uint64 `json:"fromToken,omitempty"` //my token
|
FromToken uint64 `json:"fromToken,omitempty"` // deprecated
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
Token uint64 `json:"token,omitempty"` // totp token
|
Token uint64 `json:"token,omitempty"` // if public totp token
|
||||||
ConeNatPort int `json:"coneNatPort,omitempty"` // if isPublic, is public port
|
ConeNatPort int `json:"coneNatPort,omitempty"` // if isPublic, is public port
|
||||||
NatType int `json:"natType,omitempty"`
|
NatType int `json:"natType,omitempty"`
|
||||||
HasIPv4 int `json:"hasIPv4,omitempty"`
|
HasIPv4 int `json:"hasIPv4,omitempty"`
|
||||||
@@ -200,7 +207,7 @@ type PushConnectRsp struct {
|
|||||||
Detail string `json:"detail,omitempty"`
|
Detail string `json:"detail,omitempty"`
|
||||||
NatType int `json:"natType,omitempty"`
|
NatType int `json:"natType,omitempty"`
|
||||||
HasIPv4 int `json:"hasIPv4,omitempty"`
|
HasIPv4 int `json:"hasIPv4,omitempty"`
|
||||||
IPv6 string `json:"IPv6,omitempty"`
|
IPv6 string `json:"IPv6,omitempty"` // if public relay node, ipv6 not set
|
||||||
HasUPNPorNATPMP int `json:"hasUPNPorNATPMP,omitempty"`
|
HasUPNPorNATPMP int `json:"hasUPNPorNATPMP,omitempty"`
|
||||||
ConeNatPort int `json:"coneNatPort,omitempty"` //it's not only cone, but also upnp or nat-pmp hole
|
ConeNatPort int `json:"coneNatPort,omitempty"` //it's not only cone, but also upnp or nat-pmp hole
|
||||||
FromIP string `json:"fromIP,omitempty"`
|
FromIP string `json:"fromIP,omitempty"`
|
||||||
@@ -323,6 +330,7 @@ type AppInfo struct {
|
|||||||
ShareBandwidth int `json:"shareBandWidth,omitempty"`
|
ShareBandwidth int `json:"shareBandWidth,omitempty"`
|
||||||
RelayNode string `json:"relayNode,omitempty"`
|
RelayNode string `json:"relayNode,omitempty"`
|
||||||
RelayMode string `json:"relayMode,omitempty"`
|
RelayMode string `json:"relayMode,omitempty"`
|
||||||
|
LinkMode string `json:"linkMode,omitempty"`
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
RetryTime string `json:"retryTime,omitempty"`
|
RetryTime string `json:"retryTime,omitempty"`
|
||||||
ConnectTime string `json:"connectTime,omitempty"`
|
ConnectTime string `json:"connectTime,omitempty"`
|
||||||
|
|||||||
3
totp.go
3
totp.go
@@ -25,6 +25,9 @@ func VerifyTOTP(code uint64, token uint64, ts int64) bool {
|
|||||||
if code == 0 {
|
if code == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if code == token {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if code == GenTOTP(token, ts) || code == GenTOTP(token, ts-TOTPStep) || code == GenTOTP(token, ts+TOTPStep) {
|
if code == GenTOTP(token, ts) || code == GenTOTP(token, ts-TOTPStep) || code == GenTOTP(token, ts+TOTPStep) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (conn *underlayTCP6) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func listenTCP6(port int, idleTimeout time.Duration) (*underlayTCP6, error) {
|
func listenTCP6(port int, idleTimeout time.Duration) (*underlayTCP6, error) {
|
||||||
addr, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("0.0.0.0:%d", port))
|
addr, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("[::]:%d", port))
|
||||||
l, err := net.ListenTCP("tcp6", addr)
|
l, err := net.ListenTCP("tcp6", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -83,9 +83,9 @@ func listenTCP6(port int, idleTimeout time.Duration) (*underlayTCP6, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dialTCP6(host string, port int) (*underlayTCP6, error) {
|
func dialTCP6(host string, port int) (*underlayTCP6, error) {
|
||||||
c, err := net.DialTimeout("tcp6", fmt.Sprintf("%s:%d", host, port), SymmetricHandshakeAckTimeout)
|
c, err := net.DialTimeout("tcp6", fmt.Sprintf("[%s]:%d", host, port), SymmetricHandshakeAckTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Dial %s:%d error:%s", host, port, err)
|
gLog.Printf(LvERROR, "Dial %s:%d error:%s", host, port, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &underlayTCP6{writeMtx: &sync.Mutex{}, Conn: c}, nil
|
return &underlayTCP6{writeMtx: &sync.Mutex{}, Conn: c}, nil
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ func update() {
|
|||||||
}
|
}
|
||||||
goos := runtime.GOOS
|
goos := runtime.GOOS
|
||||||
goarch := runtime.GOARCH
|
goarch := runtime.GOARCH
|
||||||
rsp, err := c.Get(fmt.Sprintf("https://openp2p.cn:27183/api/v1/update?fromver=%s&os=%s&arch=%s", OpenP2PVersion, goos, goarch))
|
rsp, err := c.Get(fmt.Sprintf("https://api.openp2p.cn:27183/api/v1/update?fromver=%s&os=%s&arch=%s", OpenP2PVersion, goos, goarch))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LvERROR, "update:query update list failed:", err)
|
gLog.Println(LvERROR, "update:query update list failed:", err)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user