mirror of
https://github.com/openp2p-cn/openp2p.git
synced 2026-04-14 18:41:57 +08:00
web console
This commit is contained in:
49
README-ZH.md
49
README-ZH.md
@@ -28,38 +28,43 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
|
||||
基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信
|
||||
|
||||
## 快速入门
|
||||
仅需简单4步就能用起来。
|
||||
下面是一个远程办公例子:在家里连入办公室Windows电脑。
|
||||
### 1.注册
|
||||
前往<https://console.openp2p.cn> 注册新用户,暂无需任何认证
|
||||
|
||||
> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p"
|
||||

|
||||
### 2.安装
|
||||
分别在本地和远程电脑下载后双击运行,一键安装
|
||||
|
||||

|
||||
|
||||
以一个最常见的例子说明OpenP2P如何使用:远程办公,在家里连入办公室Windows电脑。
|
||||
相信很多人在疫情下远程办公是刚需。
|
||||
1. 先确认办公室电脑已开启远程桌面功能(如何开启参考官方说明https://docs.microsoft.com/zh-cn/windows-server/remote/remote-desktop-services/clients/remote-desktop-allow-access)
|
||||
2. 在办公室下载最新的`OpenP2P`[下载页](https://openp2p.cn/),解压出来,在命令行执行
|
||||
```
|
||||
openp2p.exe install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
```
|
||||
|
||||
> :warning: **切记将标记大写的参数改成自己的,3个参数的长度必须>=8个字符**
|
||||
Windows默认会阻止没有花钱买它家证书签名过的程序,选择“仍要运行”即可。
|
||||
|
||||

|
||||
3. 在家里下载最新的OpenP2P,解压出来,在命令行执行
|
||||
```
|
||||
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname WindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
```
|
||||
> :warning: **切记将标记大写的参数改成自己的**
|
||||

|
||||
|
||||

|
||||
### 3.新建P2P应用
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 4.使用P2P应用
|
||||
在“MyHomePC”设备上能看到刚才创建的P2P应用,连接下图显示的“本地监听端口”即可。
|
||||
|
||||

|
||||
|
||||
在家里Windows电脑,按Win+R输入mstsc打开远程桌面,输入127.0.0.1:23389 /admin
|
||||
|
||||

|
||||

|
||||
`LISTEN ON PORT 23389 START` 看到这行日志表示P2PApp建立成功,监听23389端口。只需连接本机的127.0.0.1:23389就相当于连接公司Windows电脑的3389端口。
|
||||
|
||||
4. 在家里Windows电脑,按Win+R输入mstsc打开远程桌面,输入127.0.0.1:23389 /admin
|
||||

|
||||
|
||||

|
||||
|
||||
## 详细使用说明
|
||||
[这里](/USAGE-ZH.md)详细介绍如何使用和运行参数
|
||||
[这里](/USAGE-ZH.md)介绍如何手动运行
|
||||
|
||||
## 典型应用场景
|
||||
特别适合大流量的内网访问
|
||||
|
||||
61
README.md
61
README.md
@@ -30,52 +30,45 @@ P2P direct connection lets your devices make good use of bandwidth. Your device
|
||||
Your applicaiton can call OpenP2P with a few code to make any internal networks communicate with each other.
|
||||
|
||||
## Get Started
|
||||
A common scenario to introduce OpenP2P: remote work. At home connects to office's Linux PC .
|
||||
Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamental demand.
|
||||
Just 4 simple steps to use.
|
||||
Here's an example of remote work: connecting to an office Windows computer at home.
|
||||
|
||||
### 1.Register
|
||||
Go to <https://console.openp2p.cn> register a new user
|
||||
|
||||
> :warning: all commands in this doc, Windows env uses "openp2p.exe", Linux env uses "./openp2p"
|
||||
|
||||

|
||||
### 2.Install
|
||||
Download on local and remote computers and double-click to run, one-click installation
|
||||
|
||||
1. Make sure your office device(Linux) has opened the access of ssh.
|
||||
```
|
||||
netstat -nl | grep 22
|
||||
```
|
||||
Output sample
|
||||

|
||||

|
||||
|
||||
2. Download the latest version of `OpenP2P` [Download Page](https://openp2p.cn/),unzip the downloaded package, and execute below command line.
|
||||
```
|
||||
tar xzvf ${PackageName}
|
||||
./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
```
|
||||
By default, Windows will block programs that have not been signed by the Microsoft's certificate, and you can select "Run anyway".
|
||||
|
||||
> :warning: **Must change the parameters marked in UPPERCASE to your own. These 3 parameters must >= 8 charaters**
|
||||

|
||||
|
||||
Output sample
|
||||

|
||||

|
||||
### 3.New P2PApp
|
||||
|
||||
3. Download OpenP2P on your home device,unzip and execute below command line.
|
||||
```
|
||||
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname OfficeSSH -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 22 -srcport 22022 -protocol tcp
|
||||
```
|
||||
|
||||
> :warning: **Must change the parameters marked in UPPERCASE to your own**
|
||||

|
||||
|
||||
Output sample
|
||||

|
||||
The log of `LISTEN ON PORT 22022 START` indicates P2PApp runs successfully on your home device, listing port is 22022. Once connects to local ip:port,127.0.0.1:22022, it means the home device has conneccted to the office device's port, 22.
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
4. Test the connection between office device and home device.In your home deivce, run SSH to login the office device.
|
||||
```
|
||||
ssh -p22022 root@127.0.0.1:22022
|
||||
```
|
||||

|
||||
### 4.Use P2PApp
|
||||
You can see the P2P application you just created on the "MyHomePC" device, just connect to the "local listening port" shown in the figure below.
|
||||
|
||||

|
||||
|
||||
On MyHomePC, press Win+R and enter MSTSC to open the remote desktop, input `127.0.0.1:23389 /admin`
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## Usage
|
||||
[Here](/USAGE.md) is a detailed description of how to use and running parameters
|
||||
[Here](/USAGE.md) describes how to run manually
|
||||
|
||||
## Scenarios
|
||||
Especially suitable for large traffic intranet access.
|
||||
|
||||
26
USAGE-ZH.md
26
USAGE-ZH.md
@@ -1,36 +1,33 @@
|
||||
# 详细运行参数说明
|
||||
# 手动运行说明
|
||||
大部分情况通过<https://console.openp2p.cn> 操作即可。有些情况需要手动运行
|
||||
> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p"
|
||||
|
||||
|
||||
## 安装和监听
|
||||
```
|
||||
./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
./openp2p install -node OFFICEPC1 -token TOKEN
|
||||
或
|
||||
./openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
./openp2p -d -node OFFICEPC1 -token TOKEN
|
||||
# 注意Windows系统把“./openp2p” 换成“openp2p.exe”
|
||||
```
|
||||
>* install: 安装模式【推荐】,会安装成系统服务,这样它就能随系统自动启动
|
||||
>* -d: daemon模式。发现worker进程意外退出就会自动启动新的worker进程
|
||||
>* -node: 独一无二的节点名字,唯一标识
|
||||
>* -user: 独一无二的用户名字,该节点属于这个user
|
||||
>* -password: 密码
|
||||
>* -token: 在<console.openp2p.cn>“我的”里面找到
|
||||
>* -sharebandwidth: 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好. -1表示不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点
|
||||
>* -loglevel: 需要查看更多调试日志,设置0;默认是1
|
||||
|
||||
## 连接
|
||||
```
|
||||
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
./openp2p -d -node HOMEPC123 -token TOKEN -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389
|
||||
使用配置文件,建立多个P2PApp
|
||||
./openp2p -d -f
|
||||
./openp2p -f
|
||||
./openp2p -d
|
||||
```
|
||||
>* -appname: 这个P2P应用名字
|
||||
>* -peernode: 目标节点名字
|
||||
>* -dstip: 目标服务地址,默认本机127.0.0.1
|
||||
>* -dstport: 目标服务端口,常见的如windows远程桌面3389,Linux ssh 22
|
||||
>* -protocol: 目标服务协议 tcp、udp
|
||||
>* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置
|
||||
>* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置
|
||||
|
||||
## 配置文件
|
||||
一般保存在当前目录,安装模式下会保存到 `C:\Program Files\OpenP2P\config.json` 或 `/usr/local/openp2p/config.json`
|
||||
@@ -41,11 +38,10 @@
|
||||
{
|
||||
"network": {
|
||||
"Node": "hhd1207-222",
|
||||
"User": "USERNAME1",
|
||||
"Password": "PASSWORD1",
|
||||
"Token": "TOKEN",
|
||||
"ShareBandwidth": -1,
|
||||
"ServerHost": "api.openp2p.cn",
|
||||
"ServerPort": 27182,
|
||||
"ServerPort": 27183,
|
||||
"UDPPort1": 27182,
|
||||
"UDPPort2": 27183
|
||||
},
|
||||
@@ -57,8 +53,6 @@
|
||||
"PeerNode": "OFFICEPC1",
|
||||
"DstPort": 3389,
|
||||
"DstHost": "localhost",
|
||||
"PeerUser": "",
|
||||
"PeerPassword": ""
|
||||
},
|
||||
{
|
||||
"AppName": "OfficeServerSSH",
|
||||
@@ -67,8 +61,6 @@
|
||||
"PeerNode": "OFFICEPC1",
|
||||
"DstPort": 22,
|
||||
"DstHost": "192.168.1.5",
|
||||
"PeerUser": "",
|
||||
"PeerPassword": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
27
USAGE.md
27
USAGE.md
@@ -1,37 +1,35 @@
|
||||
# Parameters details
|
||||
|
||||
|
||||
# Parameters details
|
||||
In most cases, you can operate it through <https://console.openp2p.cn>. In some cases it is necessary to run manually
|
||||
> :warning: all commands in this doc, Windows env uses "openp2p.exe", Linux env uses "./openp2p"
|
||||
|
||||
|
||||
## Install and Listen
|
||||
```
|
||||
./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
./openp2p install -node OFFICEPC1 -token TOKEN
|
||||
Or
|
||||
./openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
./openp2p -d -node OFFICEPC1 -token TOKEN
|
||||
|
||||
```
|
||||
>* install: [recommand] will install as system service. So it will autorun when system booting.
|
||||
>* -d: daemon mode run once. When the worker process is found to exit unexpectedly, a new worker process will be automatically started
|
||||
>* -node: Unique node name, unique identification
|
||||
>* -user: Unique user name, the node belongs to this user
|
||||
>* -password: Password
|
||||
>* -token: See <console.openp2p.cn> "Profile"
|
||||
>* -sharebandwidth: Provides bandwidth when used as a shared node, the default is 10mbps. If it is a large bandwidth of optical fiber, the larger the setting, the better the effect. -1 means not shared, the node is only used in a private P2P network. Do not join the shared P2P network, which also means that you CAN NOT use other people’s shared nodes
|
||||
>* -loglevel: Need to view more debug logs, set 0; the default is 1
|
||||
|
||||
## Connect
|
||||
```
|
||||
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
./openp2p -d -node HOMEPC123 -token TOKEN -appname OfficeWindowsRemote -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389
|
||||
Create multiple P2PApp by config file
|
||||
./openp2p -d -f
|
||||
./openp2p -f
|
||||
./openp2p -d
|
||||
```
|
||||
>* -appname: This P2PApp name
|
||||
>* -peernode: Target node name
|
||||
>* -dstip: Target service address, default local 127.0.0.1
|
||||
>* -dstport: Target service port, such as windows remote desktop 3389, Linux ssh 22
|
||||
>* -protocol: Target service protocol tcp, udp
|
||||
>* -peeruser: The target user, if it is a node under the same user, no need to set
|
||||
>* -peerpassword: The target password, if it is a node under the same user, no need to set
|
||||
|
||||
## Config file
|
||||
Generally saved in the current directory, in installation mode it will be saved to `C:\Program Files\OpenP2P\config.json` or `/usr/local/openp2p/config.json`
|
||||
@@ -42,11 +40,10 @@ Configuration example
|
||||
{
|
||||
"network": {
|
||||
"Node": "hhd1207-222",
|
||||
"User": "USERNAME1",
|
||||
"Password": "PASSWORD1",
|
||||
"Token": "TOKEN",
|
||||
"ShareBandwidth": -1,
|
||||
"ServerHost": "api.openp2p.cn",
|
||||
"ServerPort": 27182,
|
||||
"ServerPort": 27183,
|
||||
"UDPPort1": 27182,
|
||||
"UDPPort2": 27183
|
||||
},
|
||||
@@ -58,8 +55,6 @@ Configuration example
|
||||
"PeerNode": "OFFICEPC1",
|
||||
"DstPort": 3389,
|
||||
"DstHost": "localhost",
|
||||
"PeerUser": "",
|
||||
"PeerPassword": ""
|
||||
},
|
||||
{
|
||||
"AppName": "OfficeServerSSH",
|
||||
@@ -68,8 +63,6 @@ Configuration example
|
||||
"PeerNode": "OFFICEPC1",
|
||||
"DstPort": 22,
|
||||
"DstHost": "192.168.1.5",
|
||||
"PeerUser": "",
|
||||
"PeerPassword": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,39 +7,39 @@ import (
|
||||
|
||||
// BandwidthLimiter ...
|
||||
type BandwidthLimiter struct {
|
||||
freeFlowTime time.Time
|
||||
bandwidth int // mbps
|
||||
freeFlow int // bytes
|
||||
maxFreeFlow int // bytes
|
||||
freeFlowMtx sync.Mutex
|
||||
ts time.Time
|
||||
bw int // mbps
|
||||
freeBytes int // bytes
|
||||
maxFreeBytes int // bytes
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
// mbps
|
||||
func newBandwidthLimiter(bw int) *BandwidthLimiter {
|
||||
return &BandwidthLimiter{
|
||||
bandwidth: bw,
|
||||
freeFlowTime: time.Now(),
|
||||
maxFreeFlow: bw * 1024 * 1024 / 8,
|
||||
freeFlow: bw * 1024 * 1024 / 8,
|
||||
bw: bw,
|
||||
ts: time.Now(),
|
||||
maxFreeBytes: bw * 1024 * 1024 / 8,
|
||||
freeBytes: bw * 1024 * 1024 / 8,
|
||||
}
|
||||
}
|
||||
|
||||
// Add ...
|
||||
func (bl *BandwidthLimiter) Add(bytes int) {
|
||||
if bl.bandwidth <= 0 {
|
||||
if bl.bw <= 0 {
|
||||
return
|
||||
}
|
||||
bl.freeFlowMtx.Lock()
|
||||
defer bl.freeFlowMtx.Unlock()
|
||||
bl.mtx.Lock()
|
||||
defer bl.mtx.Unlock()
|
||||
// calc free flow 1000*1000/1024/1024=0.954; 1024*1024/1000/1000=1.048
|
||||
bl.freeFlow += int(time.Now().Sub(bl.freeFlowTime) * time.Duration(bl.bandwidth) / 8 / 954)
|
||||
if bl.freeFlow > bl.maxFreeFlow {
|
||||
bl.freeFlow = bl.maxFreeFlow
|
||||
bl.freeBytes += int(time.Since(bl.ts) * time.Duration(bl.bw) / 8 / 954)
|
||||
if bl.freeBytes > bl.maxFreeBytes {
|
||||
bl.freeBytes = bl.maxFreeBytes
|
||||
}
|
||||
bl.freeFlow -= bytes
|
||||
bl.freeFlowTime = time.Now()
|
||||
if bl.freeFlow < 0 {
|
||||
bl.freeBytes -= bytes
|
||||
bl.ts = time.Now()
|
||||
if bl.freeBytes < 0 {
|
||||
// sleep for the overflow
|
||||
time.Sleep(time.Millisecond * time.Duration(-bl.freeFlow/(bl.bandwidth*1048/8)))
|
||||
time.Sleep(time.Millisecond * time.Duration(-bl.freeBytes/(bl.bw*1048/8)))
|
||||
}
|
||||
}
|
||||
|
||||
116
config.go
116
config.go
@@ -2,7 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -13,14 +15,14 @@ const IntValueNotSet int = -99999999
|
||||
|
||||
type AppConfig struct {
|
||||
// required
|
||||
AppName string
|
||||
Protocol string
|
||||
SrcPort int
|
||||
PeerNode string
|
||||
DstPort int
|
||||
DstHost string
|
||||
PeerUser string
|
||||
PeerPassword string
|
||||
AppName string
|
||||
Protocol string
|
||||
SrcPort int
|
||||
PeerNode string
|
||||
DstPort int
|
||||
DstHost string
|
||||
PeerUser string
|
||||
Enabled int // default:1
|
||||
// runtime info
|
||||
peerToken uint64
|
||||
peerNatType int
|
||||
@@ -40,14 +42,29 @@ type Config struct {
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
func (c *Config) add(app AppConfig) {
|
||||
func (c *Config) switchApp(app AppConfig, enabled int) {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
for i := 0; i < len(c.Apps); i++ {
|
||||
if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort {
|
||||
c.Apps[i].Enabled = enabled
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) add(app AppConfig, force bool) {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
if app.SrcPort == 0 || app.DstPort == 0 {
|
||||
gLog.Println(LevelERROR, "invalid app ", app)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(c.Apps); i++ {
|
||||
if c.Apps[i].Protocol == app.Protocol && c.Apps[i].SrcPort == app.SrcPort {
|
||||
if force {
|
||||
c.Apps[i] = app
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -85,7 +102,7 @@ func (c *Config) load() error {
|
||||
defer c.mtx.Unlock()
|
||||
data, err := ioutil.ReadFile("config.json")
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "read config.json error:", err)
|
||||
// gLog.Println(LevelERROR, "read config.json error:", err)
|
||||
return err
|
||||
}
|
||||
err = json.Unmarshal(data, &c)
|
||||
@@ -97,9 +114,9 @@ func (c *Config) load() error {
|
||||
|
||||
type NetworkConfig struct {
|
||||
// local info
|
||||
Token uint64
|
||||
Node string
|
||||
User string
|
||||
Password string
|
||||
localIP string
|
||||
ipv6 string
|
||||
hostName string
|
||||
@@ -114,3 +131,80 @@ type NetworkConfig struct {
|
||||
UDPPort1 int
|
||||
UDPPort2 int
|
||||
}
|
||||
|
||||
func parseParams() {
|
||||
serverHost := flag.String("serverhost", "api.openp2p.cn", "server host ")
|
||||
// serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug
|
||||
node := flag.String("node", "", "node name. 8-31 characters")
|
||||
token := flag.Uint64("token", 0, "token")
|
||||
peerNode := flag.String("peernode", "", "peer node name that you want to connect")
|
||||
dstIP := flag.String("dstip", "127.0.0.1", "destination ip ")
|
||||
dstPort := flag.Int("dstport", 0, "destination port ")
|
||||
srcPort := flag.Int("srcport", 0, "source port ")
|
||||
protocol := flag.String("protocol", "tcp", "tcp or udp")
|
||||
appName := flag.String("appname", "", "app name")
|
||||
flag.Bool("noshare", false, "deprecated. uses -sharebandwidth -1") // Deprecated, rm later
|
||||
shareBandwidth := flag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
|
||||
flag.Bool("f", false, "deprecated. config file") // Deprecated, rm later
|
||||
daemonMode := flag.Bool("d", false, "daemonMode")
|
||||
flag.Bool("bydaemon", false, "start by daemon") // Deprecated, rm later
|
||||
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||
flag.Parse()
|
||||
|
||||
config := AppConfig{Enabled: 1}
|
||||
config.PeerNode = *peerNode
|
||||
config.DstHost = *dstIP
|
||||
config.DstPort = *dstPort
|
||||
config.SrcPort = *srcPort
|
||||
config.Protocol = *protocol
|
||||
config.AppName = *appName
|
||||
gConf.load()
|
||||
if config.SrcPort != 0 {
|
||||
gConf.add(config, true)
|
||||
}
|
||||
gConf.mtx.Lock()
|
||||
|
||||
// spec paramters in commandline will always be used
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
if f.Name == "sharebandwidth" {
|
||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||
}
|
||||
if f.Name == "node" {
|
||||
gConf.Network.Node = *node
|
||||
}
|
||||
if f.Name == "serverhost" {
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
}
|
||||
if f.Name == "loglevel" {
|
||||
gConf.LogLevel = *logLevel
|
||||
}
|
||||
})
|
||||
|
||||
if gConf.Network.ServerHost == "" {
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
}
|
||||
if gConf.Network.Node == "" {
|
||||
gConf.Network.Node = *node
|
||||
}
|
||||
if *token != 0 {
|
||||
gConf.Network.Token = *token
|
||||
}
|
||||
if gConf.LogLevel == IntValueNotSet {
|
||||
gConf.LogLevel = *logLevel
|
||||
}
|
||||
if gConf.Network.ShareBandwidth == IntValueNotSet {
|
||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||
}
|
||||
|
||||
gConf.Network.ServerPort = 27183
|
||||
gConf.Network.UDPPort1 = 27182
|
||||
gConf.Network.UDPPort2 = 27183
|
||||
gLog.setLevel(LogLevel(gConf.LogLevel))
|
||||
gConf.mtx.Unlock()
|
||||
gConf.save()
|
||||
if *daemonMode {
|
||||
d := daemon{}
|
||||
d.run()
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
122
daemon.go
122
daemon.go
@@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kardianos/service"
|
||||
@@ -64,7 +66,7 @@ func (d *daemon) run() {
|
||||
}
|
||||
for {
|
||||
// start worker
|
||||
gLog.Println(LevelINFO, "start worker process")
|
||||
gLog.Println(LevelINFO, "start worker process, args:", args)
|
||||
execSpec := &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}
|
||||
p, err := os.StartProcess(binPath, args, execSpec)
|
||||
if err != nil {
|
||||
@@ -104,21 +106,22 @@ func (d *daemon) Control(ctrlComm string, exeAbsPath string, args []string) erro
|
||||
|
||||
// examples:
|
||||
// listen:
|
||||
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -sharebandwidth 0
|
||||
// ./openp2p install -node hhd1207-222 -token YOUR-TOKEN -sharebandwidth -1
|
||||
// listen and build p2papp:
|
||||
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -sharebandwidth 0 -peernode hhdhome-n1 -dstip 127.0.0.1 -dstport 50022 -protocol tcp -srcport 22
|
||||
// ./openp2p install -node hhd1207-222 -token YOUR-TOKEN -sharebandwidth -1 -peernode hhdhome-n1 -dstip 127.0.0.1 -dstport 50022 -protocol tcp -srcport 22
|
||||
func install() {
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p-install", LevelDEBUG, 1024*1024, LogConsole)
|
||||
gLog.Println(LevelINFO, "install start")
|
||||
defer gLog.Println(LevelINFO, "install end")
|
||||
// auto uninstall
|
||||
|
||||
uninstall()
|
||||
// save config file
|
||||
installFlag := flag.NewFlagSet("install", flag.ExitOnError)
|
||||
serverHost := installFlag.String("serverhost", "api.openp2p.cn", "server host ")
|
||||
// serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug
|
||||
user := installFlag.String("user", "", "user name. 8-31 characters")
|
||||
node := installFlag.String("node", "", "node name. 8-31 characters")
|
||||
password := installFlag.String("password", "", "user password. 8-31 characters")
|
||||
token := installFlag.Uint64("token", 0, "token")
|
||||
node := installFlag.String("node", "", "node name. 8-31 characters. if not set, it will be hostname")
|
||||
peerNode := installFlag.String("peernode", "", "peer node name that you want to connect")
|
||||
peerUser := installFlag.String("peeruser", "", "peer node user (default peeruser=user)")
|
||||
peerPassword := installFlag.String("peerpassword", "", "peer node password (default peerpassword=password)")
|
||||
dstIP := installFlag.String("dstip", "127.0.0.1", "destination ip ")
|
||||
dstPort := installFlag.Int("dstport", 0, "destination port ")
|
||||
srcPort := installFlag.Int("srcport", 0, "source port ")
|
||||
@@ -128,36 +131,48 @@ func install() {
|
||||
shareBandwidth := installFlag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
|
||||
logLevel := installFlag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||
installFlag.Parse(os.Args[2:])
|
||||
checkParams(*node, *user, *password)
|
||||
if *node != "" && len(*node) < 8 {
|
||||
gLog.Println(LevelERROR, "node name too short, it must >=8 charaters")
|
||||
os.Exit(9)
|
||||
}
|
||||
if *node == "" { // if node name not set. use os.Hostname
|
||||
hostname, _ := os.Hostname()
|
||||
node = &hostname
|
||||
}
|
||||
gConf.load() // load old config. otherwise will clear all apps
|
||||
gConf.LogLevel = *logLevel
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
gConf.Network.User = *user
|
||||
gConf.Network.Token = *token
|
||||
gConf.Network.Node = *node
|
||||
gConf.Network.Password = *password
|
||||
gConf.Network.ServerPort = 27182
|
||||
gConf.Network.ServerPort = 27183
|
||||
gConf.Network.UDPPort1 = 27182
|
||||
gConf.Network.UDPPort2 = 27183
|
||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||
config := AppConfig{}
|
||||
config := AppConfig{Enabled: 1}
|
||||
config.PeerNode = *peerNode
|
||||
config.PeerUser = *peerUser
|
||||
config.PeerPassword = *peerPassword
|
||||
config.DstHost = *dstIP
|
||||
config.DstPort = *dstPort
|
||||
config.SrcPort = *srcPort
|
||||
config.Protocol = *protocol
|
||||
config.AppName = *appName
|
||||
gConf.add(config)
|
||||
os.MkdirAll(defaultInstallPath, 0775)
|
||||
err := os.Chdir(defaultInstallPath)
|
||||
if config.SrcPort != 0 {
|
||||
gConf.add(config, true)
|
||||
}
|
||||
err := os.MkdirAll(defaultInstallPath, 0775)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "MkdirAll %s error:%s", defaultInstallPath, err)
|
||||
return
|
||||
}
|
||||
err = os.Chdir(defaultInstallPath)
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "cd error:", err)
|
||||
return
|
||||
}
|
||||
gConf.save()
|
||||
|
||||
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||
d := daemon{}
|
||||
// copy files
|
||||
|
||||
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||
binPath, _ := os.Executable()
|
||||
src, errFiles := os.Open(binPath) // can not use args[0], on Windows call openp2p is ok(=openp2p.exe)
|
||||
if errFiles != nil {
|
||||
@@ -180,14 +195,10 @@ func install() {
|
||||
dst.Close()
|
||||
|
||||
// install system service
|
||||
d := daemon{}
|
||||
|
||||
// args := []string{""}
|
||||
gLog.Println(LevelINFO, "targetPath:", targetPath)
|
||||
err = d.Control("install", targetPath, []string{"-d"})
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "install system service error:", err)
|
||||
} else {
|
||||
if err == nil {
|
||||
gLog.Println(LevelINFO, "install system service ok.")
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
@@ -199,11 +210,45 @@ func install() {
|
||||
}
|
||||
}
|
||||
|
||||
func installByFilename() {
|
||||
params := strings.Split(filepath.Base(os.Args[0]), "-")
|
||||
if len(params) < 4 {
|
||||
return
|
||||
}
|
||||
serverHost := params[1]
|
||||
token := params[2]
|
||||
gLog.Println(LevelINFO, "install start")
|
||||
targetPath := os.Args[0]
|
||||
args := []string{"install"}
|
||||
args = append(args, "-serverhost")
|
||||
args = append(args, serverHost)
|
||||
args = append(args, "-token")
|
||||
args = append(args, token)
|
||||
env := os.Environ()
|
||||
cmd := exec.Command(targetPath, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Env = env
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "install by filename, start process error:", err)
|
||||
return
|
||||
}
|
||||
gLog.Println(LevelINFO, "install end")
|
||||
fmt.Println("Press the Any Key to exit")
|
||||
fmt.Scanln()
|
||||
os.Exit(0)
|
||||
}
|
||||
func uninstall() {
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p-install", LevelDEBUG, 1024*1024, LogFileAndConsole)
|
||||
gLog.Println(LevelINFO, "uninstall start")
|
||||
defer gLog.Println(LevelINFO, "uninstall end")
|
||||
d := daemon{}
|
||||
d.Control("stop", "", nil)
|
||||
err := d.Control("uninstall", "", nil)
|
||||
err := d.Control("stop", "", nil)
|
||||
if err != nil { // service maybe not install
|
||||
return
|
||||
}
|
||||
err = d.Control("uninstall", "", nil)
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "uninstall system service error:", err)
|
||||
} else {
|
||||
@@ -211,21 +256,6 @@ func uninstall() {
|
||||
}
|
||||
binPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||
os.Remove(binPath + "0")
|
||||
os.Rename(binPath, binPath+"0")
|
||||
os.RemoveAll(defaultInstallPath)
|
||||
}
|
||||
|
||||
func checkParams(node, user, password string) {
|
||||
if len(node) < 8 {
|
||||
gLog.Println(LevelERROR, "node name too short, it must >=8 charaters")
|
||||
os.Exit(9)
|
||||
}
|
||||
if len(user) < 8 {
|
||||
gLog.Println(LevelERROR, "user name too short, it must >=8 charaters")
|
||||
os.Exit(9)
|
||||
}
|
||||
if len(password) < 8 {
|
||||
gLog.Println(LevelERROR, "password too short, it must >=8 charaters")
|
||||
os.Exit(9)
|
||||
}
|
||||
os.Remove(binPath)
|
||||
// os.RemoveAll(defaultInstallPath) // reserve config.json
|
||||
}
|
||||
|
||||
111
handlepush.go
111
handlepush.go
@@ -8,8 +8,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -30,10 +28,10 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
}
|
||||
gLog.Printf(LevelINFO, "%s is connecting...", req.From)
|
||||
gLog.Println(LevelDEBUG, "push connect response to ", req.From)
|
||||
// verify token or name&password
|
||||
if VerifyTOTP(req.Token, pn.config.User, pn.config.Password, time.Now().Unix()+(pn.serverTs-pn.localTs)) || // localTs may behind, auto adjust ts
|
||||
VerifyTOTP(req.Token, pn.config.User, pn.config.Password, time.Now().Unix()) ||
|
||||
(req.User == pn.config.User && req.Password == pn.config.Password) {
|
||||
// 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
|
||||
VerifyTOTP(req.Token, pn.config.Token, time.Now().Unix()) ||
|
||||
(req.FromToken == pn.config.Token) {
|
||||
gLog.Printf(LevelINFO, "Access Granted\n")
|
||||
config := AppConfig{}
|
||||
config.peerNatType = req.NatType
|
||||
@@ -41,7 +39,7 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
config.peerIP = req.FromIP
|
||||
config.PeerNode = req.From
|
||||
// share relay node will limit bandwidth
|
||||
if req.User != pn.config.User || req.Password != pn.config.Password {
|
||||
if req.FromToken != pn.config.Token {
|
||||
gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
|
||||
config.shareBandwidth = pn.config.ShareBandwidth
|
||||
}
|
||||
@@ -79,9 +77,6 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
config := AppConfig{}
|
||||
config.PeerNode = req.RelayName
|
||||
config.peerToken = req.RelayToken
|
||||
// set user password, maybe the relay node is your private node
|
||||
config.PeerUser = pn.config.User
|
||||
config.PeerPassword = pn.config.Password
|
||||
go func(r AddRelayTunnelReq) {
|
||||
t, errDt := pn.addDirectTunnel(config, 0)
|
||||
if errDt == nil {
|
||||
@@ -93,23 +88,25 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
|
||||
}(req)
|
||||
case MsgPushUpdate:
|
||||
gLog.Println(LevelINFO, "MsgPushUpdate")
|
||||
update() // download new version first, then exec ./openp2p update
|
||||
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||
args := []string{"update"}
|
||||
env := os.Environ()
|
||||
// Windows does not support exec syscall.
|
||||
if runtime.GOOS == "windows" {
|
||||
cmd := exec.Command(targetPath, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Env = env
|
||||
err := cmd.Run()
|
||||
if err == nil {
|
||||
os.Exit(0)
|
||||
}
|
||||
return err
|
||||
cmd := exec.Command(targetPath, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Env = env
|
||||
err := cmd.Run()
|
||||
if err == nil {
|
||||
os.Exit(0)
|
||||
}
|
||||
return syscall.Exec(targetPath, args, env)
|
||||
return err
|
||||
case MsgPushRestart:
|
||||
gLog.Println(LevelINFO, "MsgPushRestart")
|
||||
os.Exit(0)
|
||||
return err
|
||||
case MsgPushReportApps:
|
||||
gLog.Println(LevelINFO, "MsgPushReportApps")
|
||||
req := ReportApps{}
|
||||
@@ -117,6 +114,14 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
gConf.mtx.Lock()
|
||||
defer gConf.mtx.Unlock()
|
||||
for _, config := range gConf.Apps {
|
||||
appActive := 0
|
||||
i, ok := pn.apps.Load(fmt.Sprintf("%s%d", config.Protocol, config.SrcPort))
|
||||
if ok {
|
||||
app := i.(*p2pApp)
|
||||
if app.isActive() {
|
||||
appActive = 1
|
||||
}
|
||||
}
|
||||
appInfo := AppInfo{
|
||||
AppName: config.AppName,
|
||||
Protocol: config.Protocol,
|
||||
@@ -129,29 +134,11 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
PeerIP: config.peerIP,
|
||||
PeerNatType: config.peerNatType,
|
||||
RetryTime: config.retryTime.String(),
|
||||
IsActive: 1,
|
||||
IsActive: appActive,
|
||||
Enabled: config.Enabled,
|
||||
}
|
||||
req.Apps = append(req.Apps, appInfo)
|
||||
}
|
||||
// pn.apps.Range(func(_, i interface{}) bool {
|
||||
// app := i.(*p2pApp)
|
||||
// appInfo := AppInfo{
|
||||
// AppName: app.config.AppName,
|
||||
// Protocol: app.config.Protocol,
|
||||
// SrcPort: app.config.SrcPort,
|
||||
// RelayNode: app.relayNode,
|
||||
// PeerNode: app.config.PeerNode,
|
||||
// DstHost: app.config.DstHost,
|
||||
// DstPort: app.config.DstPort,
|
||||
// PeerUser: app.config.PeerUser,
|
||||
// PeerIP: app.config.peerIP,
|
||||
// PeerNatType: app.config.peerNatType,
|
||||
// RetryTime: app.config.retryTime.String(),
|
||||
// IsActive: 1,
|
||||
// }
|
||||
// req.Apps = append(req.Apps, appInfo)
|
||||
// return true
|
||||
// })
|
||||
pn.write(MsgReport, MsgReportApps, &req)
|
||||
case MsgPushEditApp:
|
||||
gLog.Println(LevelINFO, "MsgPushEditApp")
|
||||
@@ -161,7 +148,7 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
gLog.Printf(LevelERROR, "wrong MsgPushEditApp:%s %s", err, string(msg[openP2PHeaderSize:]))
|
||||
return err
|
||||
}
|
||||
var oldConf AppConfig
|
||||
oldConf := AppConfig{Enabled: 1}
|
||||
// protocol0+srcPort0 exist, delApp
|
||||
oldConf.AppName = newApp.AppName
|
||||
oldConf.Protocol = newApp.Protocol0
|
||||
@@ -175,12 +162,42 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
||||
newConf := oldConf
|
||||
newConf.Protocol = newApp.Protocol
|
||||
newConf.SrcPort = newApp.SrcPort
|
||||
gConf.add(newConf)
|
||||
gConf.save()
|
||||
pn.DeleteApp(oldConf) // save quickly for the next request reportApplist
|
||||
gConf.add(newConf, false)
|
||||
gConf.save() // save quickly for the next request reportApplist
|
||||
pn.DeleteApp(oldConf) // DeleteApp may cost some times, execute at the end
|
||||
// autoReconnect will auto AddApp
|
||||
// pn.AddApp(config)
|
||||
// TODO: report result
|
||||
case MsgPushEditNode:
|
||||
gLog.Println(LevelINFO, "MsgPushEditNode")
|
||||
req := EditNode{}
|
||||
err := json.Unmarshal(msg[openP2PHeaderSize:], &req)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong MsgPushEditNode:%s %s", err, string(msg[openP2PHeaderSize:]))
|
||||
return err
|
||||
}
|
||||
gConf.mtx.Lock()
|
||||
gConf.Network.Node = req.NewName
|
||||
gConf.Network.ShareBandwidth = req.Bandwidth
|
||||
gConf.mtx.Unlock()
|
||||
gConf.save()
|
||||
// TODO: hot reload
|
||||
os.Exit(0)
|
||||
case MsgPushSwitchApp:
|
||||
gLog.Println(LevelINFO, "MsgPushSwitchApp")
|
||||
app := AppInfo{}
|
||||
err := json.Unmarshal(msg[openP2PHeaderSize:], &app)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong MsgPushSwitchApp:%s %s", err, string(msg[openP2PHeaderSize:]))
|
||||
return err
|
||||
}
|
||||
config := AppConfig{Enabled: app.Enabled, SrcPort: app.SrcPort, Protocol: app.Protocol}
|
||||
gLog.Println(LevelINFO, app.AppName, " switch to ", app.Enabled)
|
||||
gConf.switchApp(config, app.Enabled)
|
||||
if app.Enabled == 0 {
|
||||
// disable APP
|
||||
pn.DeleteApp(config)
|
||||
}
|
||||
default:
|
||||
pn.msgMapMtx.Lock()
|
||||
ch := pn.msgMap[pushHead.From]
|
||||
|
||||
95
openp2p.go
95
openp2p.go
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
@@ -14,9 +13,8 @@ func main() {
|
||||
binDir := filepath.Dir(os.Args[0])
|
||||
os.Chdir(binDir) // for system service
|
||||
gLog = InitLogger(binDir, "openp2p", LevelDEBUG, 1024*1024, LogFileAndConsole)
|
||||
|
||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||
// TODO: install sub command, deamon process
|
||||
// groups := flag.String("groups", "", "you could join in several groups. like: GroupName1:Password1;GroupName2:Password2; group name 8-31 characters")
|
||||
if len(os.Args) > 1 {
|
||||
switch os.Args[1] {
|
||||
case "version", "-v", "--version":
|
||||
@@ -24,7 +22,6 @@ func main() {
|
||||
return
|
||||
case "update":
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LevelDEBUG, 1024*1024, LogFileAndConsole)
|
||||
update()
|
||||
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||
d := daemon{}
|
||||
err := d.Control("restart", targetPath, nil)
|
||||
@@ -41,95 +38,11 @@ func main() {
|
||||
uninstall()
|
||||
return
|
||||
}
|
||||
}
|
||||
serverHost := flag.String("serverhost", "api.openp2p.cn", "server host ")
|
||||
// serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug
|
||||
user := flag.String("user", "", "user name. 8-31 characters")
|
||||
node := flag.String("node", "", "node name. 8-31 characters")
|
||||
password := flag.String("password", "", "user password. 8-31 characters")
|
||||
peerNode := flag.String("peernode", "", "peer node name that you want to connect")
|
||||
peerUser := flag.String("peeruser", "", "peer node user (default peeruser=user)")
|
||||
peerPassword := flag.String("peerpassword", "", "peer node password (default peerpassword=password)")
|
||||
dstIP := flag.String("dstip", "127.0.0.1", "destination ip ")
|
||||
dstPort := flag.Int("dstport", 0, "destination port ")
|
||||
srcPort := flag.Int("srcport", 0, "source port ")
|
||||
protocol := flag.String("protocol", "tcp", "tcp or udp")
|
||||
appName := flag.String("appname", "", "app name")
|
||||
flag.Bool("noshare", false, "deprecated. uses -sharebandwidth -1") // Deprecated, rm later
|
||||
shareBandwidth := flag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
|
||||
flag.Bool("f", false, "deprecated. config file") // Deprecated, rm later
|
||||
daemonMode := flag.Bool("d", false, "daemonMode")
|
||||
flag.Bool("bydaemon", false, "start by daemon") // Deprecated, rm later
|
||||
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||
flag.Parse()
|
||||
|
||||
config := AppConfig{}
|
||||
config.PeerNode = *peerNode
|
||||
config.PeerUser = *peerUser
|
||||
config.PeerPassword = *peerPassword
|
||||
config.DstHost = *dstIP
|
||||
config.DstPort = *dstPort
|
||||
config.SrcPort = *srcPort
|
||||
config.Protocol = *protocol
|
||||
config.AppName = *appName
|
||||
// add command config first
|
||||
gConf.add(config)
|
||||
gConf.load()
|
||||
gConf.mtx.Lock()
|
||||
|
||||
// spec paramters in commandline will always be used
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
if f.Name == "sharebandwidth" {
|
||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||
}
|
||||
if f.Name == "node" {
|
||||
gConf.Network.Node = *node
|
||||
}
|
||||
if f.Name == "user" {
|
||||
gConf.Network.User = *user
|
||||
}
|
||||
if f.Name == "password" {
|
||||
gConf.Network.Password = *password
|
||||
}
|
||||
if f.Name == "serverhost" {
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
}
|
||||
if f.Name == "loglevel" {
|
||||
gConf.LogLevel = *logLevel
|
||||
}
|
||||
})
|
||||
|
||||
if gConf.Network.ServerHost == "" {
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
}
|
||||
if gConf.Network.Node == "" {
|
||||
gConf.Network.Node = *node
|
||||
}
|
||||
if gConf.Network.User == "" {
|
||||
gConf.Network.User = *user
|
||||
}
|
||||
if gConf.Network.Password == "" {
|
||||
gConf.Network.Password = *password
|
||||
}
|
||||
if gConf.LogLevel == IntValueNotSet {
|
||||
gConf.LogLevel = *logLevel
|
||||
}
|
||||
if gConf.Network.ShareBandwidth == IntValueNotSet {
|
||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||
} else {
|
||||
installByFilename()
|
||||
}
|
||||
|
||||
gConf.Network.ServerPort = 27182
|
||||
gConf.Network.UDPPort1 = 27182
|
||||
gConf.Network.UDPPort2 = 27183
|
||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||
gLog.setLevel(LogLevel(gConf.LogLevel))
|
||||
gConf.mtx.Unlock()
|
||||
gConf.save()
|
||||
if *daemonMode {
|
||||
d := daemon{}
|
||||
d.run()
|
||||
return
|
||||
}
|
||||
parseParams()
|
||||
gLog.Println(LevelINFO, &gConf)
|
||||
setFirewall()
|
||||
network := P2PNetworkInstance(&gConf.Network)
|
||||
|
||||
@@ -76,8 +76,7 @@ func (app *p2pApp) listenTCP() error {
|
||||
gLog.Printf(LevelDEBUG, "Accept overlayID:%d", otcp.id)
|
||||
// tell peer connect
|
||||
req := OverlayConnectReq{ID: otcp.id,
|
||||
User: app.config.PeerUser,
|
||||
Password: app.config.PeerPassword,
|
||||
Token: app.tunnel.pn.config.Token,
|
||||
DstIP: app.config.DstHost,
|
||||
DstPort: app.config.DstPort,
|
||||
Protocol: app.config.Protocol,
|
||||
@@ -109,7 +108,9 @@ func (app *p2pApp) listen() error {
|
||||
go app.relayHeartbeatLoop()
|
||||
}
|
||||
for app.running {
|
||||
if app.config.Protocol == "tcp" {
|
||||
if app.config.Protocol == "udp" {
|
||||
app.listenTCP()
|
||||
} else {
|
||||
app.listenTCP()
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
|
||||
@@ -97,12 +97,8 @@ func (pn *P2PNetwork) runAll() {
|
||||
gConf.mtx.Lock()
|
||||
defer gConf.mtx.Unlock()
|
||||
for _, config := range gConf.Apps {
|
||||
// set default peer user password
|
||||
if config.PeerPassword == "" {
|
||||
config.PeerPassword = gConf.Network.Password
|
||||
}
|
||||
if config.PeerUser == "" {
|
||||
config.PeerUser = gConf.Network.User
|
||||
if config.Enabled == 0 {
|
||||
continue
|
||||
}
|
||||
if config.AppName == "" {
|
||||
config.AppName = fmt.Sprintf("%s%d", config.Protocol, config.SrcPort)
|
||||
@@ -249,7 +245,6 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
PeerNode: config.PeerNode,
|
||||
DstPort: config.DstPort,
|
||||
DstHost: config.DstHost,
|
||||
PeerUser: config.PeerUser,
|
||||
PeerNatType: peerNatType,
|
||||
PeerIP: peerIP,
|
||||
ShareBandwidth: pn.config.ShareBandwidth,
|
||||
@@ -257,7 +252,9 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
Version: OpenP2PVersion,
|
||||
}
|
||||
pn.write(MsgReport, MsgReportConnect, &req)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app := p2pApp{
|
||||
id: appID,
|
||||
key: appKey,
|
||||
@@ -387,8 +384,7 @@ func (pn *P2PNetwork) init() error {
|
||||
u := url.URL{Scheme: "wss", Host: gatewayURL, Path: forwardPath}
|
||||
q := u.Query()
|
||||
q.Add("node", pn.config.Node)
|
||||
q.Add("user", pn.config.User)
|
||||
q.Add("password", pn.config.Password)
|
||||
q.Add("token", fmt.Sprintf("%d", pn.config.Token))
|
||||
q.Add("version", OpenP2PVersion)
|
||||
q.Add("nattype", fmt.Sprintf("%d", pn.config.natType))
|
||||
q.Add("sharebandwidth", fmt.Sprintf("%d", pn.config.ShareBandwidth))
|
||||
@@ -460,8 +456,15 @@ func (pn *P2PNetwork) handleMessage(t int, msg []byte) {
|
||||
pn.running = false
|
||||
} else {
|
||||
pn.serverTs = rsp.Ts
|
||||
pn.config.Token = rsp.Token
|
||||
pn.config.User = rsp.User
|
||||
gConf.mtx.Lock()
|
||||
gConf.Network.Token = rsp.Token
|
||||
gConf.Network.User = rsp.User
|
||||
gConf.mtx.Unlock()
|
||||
gConf.save()
|
||||
pn.localTs = time.Now().Unix()
|
||||
gLog.Printf(LevelINFO, "login ok. Server ts=%d, local ts=%d", rsp.Ts, pn.localTs)
|
||||
gLog.Printf(LevelINFO, "login ok. user=%s,Server ts=%d, local ts=%d", rsp.User, rsp.Ts, pn.localTs)
|
||||
}
|
||||
case MsgHeartbeat:
|
||||
gLog.Printf(LevelDEBUG, "P2PNetwork heartbeat ok")
|
||||
@@ -561,12 +564,15 @@ func (pn *P2PNetwork) read(node string, mainType uint16, subType uint16, timeout
|
||||
} else {
|
||||
nodeID = nodeNameToID(node)
|
||||
}
|
||||
pn.msgMapMtx.Lock()
|
||||
ch := pn.msgMap[nodeID]
|
||||
pn.msgMapMtx.Unlock()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
gLog.Printf(LevelERROR, "wait msg%d:%d timeout", mainType, subType)
|
||||
return
|
||||
case msg := <-pn.msgMap[nodeID]:
|
||||
case msg := <-ch:
|
||||
head = &openP2PHeader{}
|
||||
err := binary.Read(bytes.NewReader(msg[:openP2PHeaderSize]), binary.LittleEndian, head)
|
||||
if err != nil {
|
||||
|
||||
@@ -55,10 +55,9 @@ func (t *P2PTunnel) connect() error {
|
||||
gLog.Printf(LevelDEBUG, "start p2pTunnel to %s ", t.config.PeerNode)
|
||||
t.isServer = false
|
||||
req := PushConnectReq{
|
||||
User: t.config.PeerUser,
|
||||
Password: t.config.PeerPassword,
|
||||
Token: t.config.peerToken,
|
||||
From: t.pn.config.Node,
|
||||
FromToken: t.pn.config.Token,
|
||||
FromIP: t.pn.config.publicIP,
|
||||
ConeNatPort: t.coneNatPort,
|
||||
NatType: t.pn.config.natType,
|
||||
@@ -326,9 +325,9 @@ func (t *P2PTunnel) readLoop() {
|
||||
gLog.Printf(LevelERROR, "wrong MsgOverlayConnectReq:%s", err)
|
||||
continue
|
||||
}
|
||||
// app connect only accept user/password, avoid someone using the share relay node's token
|
||||
if req.User != t.pn.config.User || req.Password != t.pn.config.Password {
|
||||
gLog.Println(LevelERROR, "Access Denied:", req.User)
|
||||
// app connect only accept token(not relay totp token), avoid someone using the share relay node's token
|
||||
if req.Token != t.pn.config.Token {
|
||||
gLog.Println(LevelERROR, "Access Denied:", req.Token)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
30
protocol.go
30
protocol.go
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const OpenP2PVersion = "0.99.0"
|
||||
const OpenP2PVersion = "1.0.0"
|
||||
const ProducnName string = "openp2p"
|
||||
|
||||
type openP2PHeader struct {
|
||||
@@ -80,6 +80,9 @@ const (
|
||||
MsgPushReportApps = 7
|
||||
MsgPushQuicConnect = 8
|
||||
MsgPushEditApp = 9
|
||||
MsgPushSwitchApp = 10
|
||||
MsgPushRestart = 11
|
||||
MsgPushEditNode = 12
|
||||
)
|
||||
|
||||
// MsgP2P sub type message
|
||||
@@ -167,9 +170,8 @@ func nodeNameToID(name string) uint64 {
|
||||
|
||||
type PushConnectReq struct {
|
||||
From string `json:"from,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Token uint64 `json:"token,omitempty"`
|
||||
FromToken uint64 `json:"fromToken,omitempty"` //my token
|
||||
Token uint64 `json:"token,omitempty"` // totp token
|
||||
ConeNatPort int `json:"coneNatPort,omitempty"`
|
||||
NatType int `json:"natType,omitempty"`
|
||||
FromIP string `json:"fromIP,omitempty"`
|
||||
@@ -193,6 +195,8 @@ type PushRsp struct {
|
||||
type LoginRsp struct {
|
||||
Error int `json:"error,omitempty"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Token uint64 `json:"token,omitempty"`
|
||||
Ts int64 `json:"ts,omitempty"`
|
||||
}
|
||||
|
||||
@@ -213,8 +217,7 @@ type P2PHandshakeReq struct {
|
||||
|
||||
type OverlayConnectReq struct {
|
||||
ID uint64 `json:"id,omitempty"`
|
||||
User string `json:"user,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Token uint64 `json:"token,omitempty"` // not totp token
|
||||
DstIP string `json:"dstIP,omitempty"`
|
||||
DstPort int `json:"dstPort,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
@@ -294,6 +297,7 @@ type AppInfo struct {
|
||||
Version string `json:"version,omitempty"`
|
||||
RetryTime string `json:"retryTime,omitempty"`
|
||||
IsActive int `json:"isActive,omitempty"`
|
||||
Enabled int `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
type ReportApps struct {
|
||||
@@ -324,3 +328,17 @@ type NetInfo struct {
|
||||
ASNOrg string `json:"asn_org,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
}
|
||||
|
||||
type ProfileInfo struct {
|
||||
User string `json:"user,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
Addtime string `json:"addtime,omitempty"`
|
||||
}
|
||||
|
||||
type EditNode struct {
|
||||
NewName string `json:"newName,omitempty"`
|
||||
Bandwidth int `json:"bandwidth,omitempty"`
|
||||
}
|
||||
|
||||
2
quic.go
2
quic.go
@@ -99,7 +99,7 @@ func (conn *quicConn) Accept() error {
|
||||
}
|
||||
|
||||
func listenQuic(addr string, idleTimeout time.Duration) (*quicConn, error) {
|
||||
gLog.Println(LevelINFO, "quic listen on ", addr)
|
||||
gLog.Println(LevelDEBUG, "quic listen on ", addr)
|
||||
listener, err := quic.ListenAddr(addr, generateTLSConfig(),
|
||||
&quic.Config{Versions: quicVersion, MaxIdleTimeout: idleTimeout, DisablePathMTUDiscovery: true})
|
||||
if err != nil {
|
||||
|
||||
10
totp.go
10
totp.go
@@ -8,9 +8,11 @@ import (
|
||||
)
|
||||
|
||||
const TOTPStep = 30 // 30s
|
||||
func GenTOTP(user string, password string, ts int64) uint64 {
|
||||
func GenTOTP(token uint64, ts int64) uint64 {
|
||||
step := ts / TOTPStep
|
||||
mac := hmac.New(sha256.New, []byte(user+password))
|
||||
tbuff := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(tbuff, token)
|
||||
mac := hmac.New(sha256.New, tbuff)
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, uint64(step))
|
||||
mac.Write(b)
|
||||
@@ -19,11 +21,11 @@ func GenTOTP(user string, password string, ts int64) uint64 {
|
||||
return num
|
||||
}
|
||||
|
||||
func VerifyTOTP(code uint64, user string, password string, ts int64) bool {
|
||||
func VerifyTOTP(code uint64, token uint64, ts int64) bool {
|
||||
if code == 0 {
|
||||
return false
|
||||
}
|
||||
if code == GenTOTP(user, password, ts) || code == GenTOTP(user, password, ts-TOTPStep) || code == GenTOTP(user, password, ts+TOTPStep) {
|
||||
if code == GenTOTP(token, ts) || code == GenTOTP(token, ts-TOTPStep) || code == GenTOTP(token, ts+TOTPStep) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
14
totp_test.go
14
totp_test.go
@@ -9,24 +9,24 @@ import (
|
||||
func TestTOTP(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
ts := time.Now().Unix()
|
||||
code := GenTOTP("testuser1", "testpassword1", ts)
|
||||
code := GenTOTP(13666999958022769123, ts)
|
||||
t.Log(code)
|
||||
if !VerifyTOTP(code, "testuser1", "testpassword1", ts) {
|
||||
if !VerifyTOTP(code, 13666999958022769123, ts) {
|
||||
t.Error("TOTP error")
|
||||
}
|
||||
if !VerifyTOTP(code, "testuser1", "testpassword1", ts-10) {
|
||||
if !VerifyTOTP(code, 13666999958022769123, ts-10) {
|
||||
t.Error("TOTP error")
|
||||
}
|
||||
if !VerifyTOTP(code, "testuser1", "testpassword1", ts+10) {
|
||||
if !VerifyTOTP(code, 13666999958022769123, ts+10) {
|
||||
t.Error("TOTP error")
|
||||
}
|
||||
if VerifyTOTP(code, "testuser1", "testpassword1", ts+60) {
|
||||
if VerifyTOTP(code, 13666999958022769123, ts+60) {
|
||||
t.Error("TOTP error")
|
||||
}
|
||||
if VerifyTOTP(code, "testuser2", "testpassword1", ts+1) {
|
||||
if VerifyTOTP(code, 13666999958022769124, ts+1) {
|
||||
t.Error("TOTP error")
|
||||
}
|
||||
if VerifyTOTP(code, "testuser1", "testpassword2", ts+1) {
|
||||
if VerifyTOTP(code, 13666999958022769125, ts+1) {
|
||||
t.Error("TOTP error")
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
||||
@@ -27,7 +27,7 @@ func update() {
|
||||
}
|
||||
goos := runtime.GOOS
|
||||
goarch := runtime.GOARCH
|
||||
rsp, err := c.Get(fmt.Sprintf("https://openp2p.cn:27182/api/v1/update?fromver=%s&os=%s&arch=%s", OpenP2PVersion, goos, goarch))
|
||||
rsp, err := c.Get(fmt.Sprintf("https://openp2p.cn:27183/api/v1/update?fromver=%s&os=%s&arch=%s", OpenP2PVersion, goos, goarch))
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "update:query update list failed:", err)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user