Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c1551d951 | ||
|
|
dd3d87c3d2 | ||
|
|
a28fc33b66 | ||
|
|
f12059d889 | ||
|
|
a2387fed68 | ||
|
|
8353c1c3dd | ||
|
|
a9250737f1 | ||
|
|
c83a57f014 | ||
|
|
8551264a15 | ||
|
|
1ef0f919d9 | ||
|
|
f01ca64dd9 | ||
|
|
c6f50992c3 |
52
README-ZH.md
@@ -1,10 +1,12 @@
|
||||
[English](/README.md)|中文
|
||||
# [English](/README.md)|中文
|
||||
网站: [openp2p.cn](https://openp2p.cn)
|
||||
## OpenP2P是什么
|
||||
它是一个开源、免费、轻量级的P2P共享网络。任何设备接入OpenP2P,就可以随时随地访问它们。
|
||||
它是一个开源、免费、轻量级的P2P共享网络。任何设备接入OpenP2P,随时随地访问它们。相比BT网络用来共享文件,OpenP2P网络用来共享带宽。
|
||||
我们的目标是:充分利用带宽,利用共享节点转发数据,建设一个远程连接的通用基础设施。
|
||||
|
||||
## 为什么选择OpenP2P
|
||||
### 免费
|
||||
完全免费,满足大部分用户的核心白票需求。不像其它类似的产品,我们不需要有公网IP的服务器,不需要花钱买服务。
|
||||
完全免费,满足大部分用户的核心白票需求。不像其它类似的产品,OpenP2P不需要有公网IP的服务器,不需要花钱买服务。了解它原理即可理解为什么能做到免费。
|
||||
### 安全
|
||||
代码开源,接受各位大佬检验。下面详细展开
|
||||
### 轻量
|
||||
@@ -18,41 +20,47 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
|
||||
基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信
|
||||
|
||||
## 快速入门
|
||||
|
||||
> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p"
|
||||
|
||||
|
||||
以一个最常见的例子说明OpenP2P如何使用:远程办公,在家里连入办公室Windows电脑。
|
||||
相信很多人在疫情下远程办公是刚需。
|
||||
1. 先确认办公室电脑已开启远程桌面功能(如何开启参考官方说明https://docs.microsoft.com/zh-cn/windows-server/remote/remote-desktop-services/clients/remote-desktop-allow-access)
|
||||
2. 在办公室下载最新的OpenP2P(补上URL),解压出来,在命令行执行
|
||||
2. 在办公室下载最新的`OpenP2P`[下载页](https://openp2p.cn/),解压出来,在命令行执行
|
||||
```
|
||||
openp2p.exe -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
openp2p.exe install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
```
|
||||
|
||||
`切记将标记大写的参数改成自己的`
|
||||
> :warning: **切记将标记大写的参数改成自己的,3个参数的长度必须>=8个字符**
|
||||
|
||||

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

|
||||

|
||||
`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
|
||||
4. 在家里Windows电脑,按Win+R输入mstsc打开远程桌面,输入127.0.0.1:23389 /admin
|
||||

|
||||
|
||||

|
||||
|
||||
## [详细使用说明](/USAGE-ZH.md)
|
||||
## 详细使用说明
|
||||
[这里](/USAGE-ZH.md)详细介绍如何使用和运行参数
|
||||
|
||||
## 典型应用场景
|
||||
特别适合大流量的内网访问
|
||||
### 远程办公
|
||||
Windows MSTSC、VNC等远程桌面,SSH,内网各种ERP系统
|
||||
### 远程访问NAS
|
||||
管理大量视频、图片
|
||||
### 远程监控摄像头
|
||||
### 远程刷机
|
||||
### 远程数据备份
|
||||
>* 远程办公: Windows MSTSC、VNC等远程桌面,SSH,内网各种ERP系统
|
||||
>* 远程访问内网ERP系统
|
||||
>* 远程访问NAS: 管理大量视频、图片
|
||||
>* 远程监控摄像头
|
||||
>* 远程刷机
|
||||
>* 远程数据备份
|
||||
---
|
||||
## 概要设计
|
||||
### 原型
|
||||
@@ -65,7 +73,7 @@ Windows MSTSC、VNC等远程桌面,SSH,内网各种ERP系统
|
||||
## 共享
|
||||
默认会开启共享限速10mbps,只有你用户下提供了共享节点才能使用别人的共享节点。这非常公平,也是这个项目的初衷。
|
||||
我们建议你在带宽足够的地方(比如办公室,家里的百兆光纤)加入共享网络。
|
||||
如果你仍然不想共享任何节点,请查看运行参数
|
||||
如果你仍然不想共享任何节点,请查看[详细使用说明](/USAGE-ZH.md)
|
||||
## 安全性
|
||||
加入OpenP2P共享网络的节点,只能凭授权访问。共享节点只会中转数据,别人无法访问内网任何资源。
|
||||
### TLS1.3+AES
|
||||
@@ -102,7 +110,7 @@ go build
|
||||
14. 内网直连优化,用处不大,估计就用户测试时用到
|
||||
|
||||
远期计划:
|
||||
1. 彻底地分布式去中心化设计
|
||||
1. 利用区块链技术去中心化,让共享设备的用户有收益,从而促进更多用户共享,达到正向闭环。
|
||||
2. 企业级支持,可以更好地管理大量设备,和更安全更细的权限控制
|
||||
|
||||
## 参与贡献
|
||||
@@ -111,9 +119,7 @@ TODO或ISSUE里如果有你擅长的领域,或者你有特别好的主意,
|
||||
它是一个中国人发起的项目,更懂国内网络环境,更懂用户需求,更好的企业级支持
|
||||
## 技术交流
|
||||
QQ群:16947733
|
||||
邮箱:openp2p.cn@gmail.com 271357901@qq.com
|
||||
第一时间获得最新版本消息,以及一些最新IT业界动态
|
||||
微信公众号:openp2p
|
||||
微博:https://weibo.com/openp2p
|
||||
邮箱:openp2p.cn@gmail.com tenderiron@139.com
|
||||
|
||||
## 免责声明
|
||||
本项目开源供大家学习和免费使用,禁止用于非法用途,任何不当使用本项目或意外造成的损失,本项目及相关人员不会承担任何责任。
|
||||
|
||||
57
README.md
@@ -1,9 +1,11 @@
|
||||
English|[中文](/README-ZH.md)
|
||||
# English|[中文](/README-ZH.md)
|
||||
Website: [openp2p.cn](https://openp2p.cn)
|
||||
## What is OpenP2P
|
||||
It is an open source, free, and lightweight P2P sharing network. As long as any device joins in, you can access them anywhere
|
||||
It is an open source, free, and lightweight P2P sharing network. As long as any device joins in, you can access them anywhere. Compared with the BT network used to share files, the OpenP2P network is used to share bandwidth.
|
||||
Our goal is to make full use of bandwidth, use shared nodes to relay data, and build a common infrastructure for remote connections.
|
||||
## Why OpenP2P
|
||||
### Free
|
||||
Totaly free, fullfills most of users(especially free-rider). Unlike other similar products, we don't need a server with public IP, and don't need to pay for services.
|
||||
Totaly free, fullfills most of users(especially free-rider). Unlike other similar products, OpenP2p doesn't need a server with public IP, and doesn't need to pay for services.By understanding its principle, you can understand why it can be done for free.
|
||||
|
||||
### Safe
|
||||
Open source, trustable(see details below)
|
||||
@@ -24,6 +26,9 @@ Your applicaiton can call OpenP2P with a few code to make any internal networks
|
||||
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.
|
||||
|
||||
> :warning: all commands in this doc, Windows env uses "openp2p.exe", Linux env uses "./openp2p"
|
||||
|
||||
|
||||
1. Make sure your office device(Linux) has opened the access of ssh.
|
||||
```
|
||||
netstat -nl | grep 22
|
||||
@@ -31,24 +36,27 @@ Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamenta
|
||||
Output sample
|
||||

|
||||
|
||||
2. Download the latest version of OpenP2P(TBC),unzip the downloaded package, and execute below command line.
|
||||
2. Download the latest version of `OpenP2P` [Download Page](https://openp2p.cn/),unzip the downloaded package, and execute below command line.
|
||||
```
|
||||
tar xvf openp2p0.95.3.linux-amd64.tar.gz
|
||||
openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
tar xzvf ${PackageName}
|
||||
./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
```
|
||||
`Must change the parameters marked in uppercase to your own`
|
||||
|
||||
> :warning: **Must change the parameters marked in UPPERCASE to your own. These 3 parameters must >= 8 charaters**
|
||||
|
||||
Output sample
|
||||

|
||||
|
||||
3. Download the same package of OpenP2P(TBC) on your home device,unzip and execute below command line.
|
||||
3. Download OpenP2P on your home device,unzip and execute below command line.
|
||||
```
|
||||
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 --peernode OFFICEPC1 --dstip 127.0.0.1 --dstport 22 --srcport 22022 --protocol tcp
|
||||
```
|
||||
`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.
|
||||
|
||||
> :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.
|
||||

|
||||
|
||||
|
||||
@@ -59,18 +67,17 @@ Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamenta
|
||||

|
||||
|
||||
|
||||
## [Usage](/USAGE.md)
|
||||
## Usage
|
||||
[Here](/USAGE.md) is a detailed description of how to use and running parameters
|
||||
|
||||
## Scenarios
|
||||
Especially suitable for large traffic intranet access.
|
||||
### Remote work
|
||||
Windows MSTSC, VNC and other remote desktops, SSH, various ERP systems in the intranet
|
||||
|
||||
### Remote Access NAS
|
||||
Manage a large number of videos and pictures
|
||||
### Remote Access Camera
|
||||
### Remote Flashing Phone
|
||||
### Remotely Data Backup
|
||||
>* Remote work: Windows MSTSC, VNC and other remote desktops, SSH, various ERP systems in the intranet
|
||||
>* Remote access ERP systems in the intranet
|
||||
>* Remote access NAS: Manage a large number of videos and pictures
|
||||
>* Remote access camera
|
||||
>* Remote flashing phone
|
||||
>* Remotely data backup
|
||||
---
|
||||
## Overview Design
|
||||
### Prototype
|
||||
@@ -84,7 +91,7 @@ P2PAPP is the most import concept in this project, one P2PApp is able to map the
|
||||
## Share
|
||||
10mbps is its default setting of share speed limit. Only when your users have shared their nodes, they are allowed to use others' shared nodes. This is very fair, and it is also the original intention of this project.
|
||||
We recommend that you join a shared network in a place with sufficient bandwidth (such as an office or home with 100M optical fiber).
|
||||
If you are still not willing to contribute any node to the OpenP2P share network, please refer to the operating parameters for your own setting.
|
||||
If you are still not willing to contribute any node to the OpenP2P share network, please refer to the [usage](/USAGE.md) for your own setting.
|
||||
## Safety
|
||||
The nodes which have joined the OpenP2P share network can vist each other by authentications. Shared nodes will only relay data, and others cannot access any resources in the intranet.
|
||||
|
||||
@@ -123,7 +130,7 @@ Short-Term:
|
||||
|
||||
|
||||
Long-Term:
|
||||
1. Decentration and distribution.
|
||||
1. Use blockchain technology to decentralize, so that users who share equipment have benefits, thereby promoting more users to share, and achieving a positive closed loop.
|
||||
2. Enterprise-level product can well manage large scale equipment and ACL.
|
||||
|
||||
|
||||
@@ -135,10 +142,6 @@ QQ Group: 16947733
|
||||
|
||||
Email: openp2p.cn@gmail.com tenderiron@139.com
|
||||
|
||||
Get the latest version news, and some of the latest IT industry trends
|
||||
|
||||
WeChat public account: openp2p
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
50
USAGE-ZH.md
@@ -1,33 +1,42 @@
|
||||
# 详细运行参数说明
|
||||
> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p"
|
||||
|
||||
## 监听
|
||||
|
||||
## 安装和监听
|
||||
```
|
||||
openp2p.exe -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
或
|
||||
./openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
# 注意Windows系统把“./openp2p” 换成“openp2p.exe”
|
||||
```
|
||||
>* -d daemon模式,推荐使用。发现worker进程意外退出就会自动启动新的worker进程
|
||||
>* -node 独一无二的节点名字,唯一标识
|
||||
>* -user 独一无二的用户名字,该节点属于这个user
|
||||
>* -password 密码
|
||||
>* -sharebandwidth 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好
|
||||
>* -loglevel 需要查看更多调试日志,设置0;默认是1
|
||||
>* -noshare 不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点
|
||||
>* install: 安装模式【推荐】,会安装成系统服务,这样它就能随系统自动启动
|
||||
>* -d: daemon模式。发现worker进程意外退出就会自动启动新的worker进程
|
||||
>* -node: 独一无二的节点名字,唯一标识
|
||||
>* -user: 独一无二的用户名字,该节点属于这个user
|
||||
>* -password: 密码
|
||||
>* -sharebandwidth: 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好
|
||||
>* -loglevel: 需要查看更多调试日志,设置0;默认是1
|
||||
>* -noshare: 不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点
|
||||
|
||||
## 连接
|
||||
```
|
||||
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
使用配置文件,建立多个P2PApp
|
||||
./openp2p -d -f
|
||||
./openp2p -f
|
||||
```
|
||||
>* -peernode 目标节点名字
|
||||
>* -dstip 目标服务地址,默认本机127.0.0.1
|
||||
>* -dstport 目标服务端口,常见的如windows远程桌面3389,Linux ssh 22
|
||||
>* -protocol 目标服务协议 tcp、udp
|
||||
>* -peeruser 目标用户,如果是同一个用户下的节点,则无需设置
|
||||
>* -peerpassword 目标密码,如果是同一个用户下的节点,则无需设置
|
||||
>* -f 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json)
|
||||
>* -peernode: 目标节点名字
|
||||
>* -dstip: 目标服务地址,默认本机127.0.0.1
|
||||
>* -dstport: 目标服务端口,常见的如windows远程桌面3389,Linux ssh 22
|
||||
>* -protocol: 目标服务协议 tcp、udp
|
||||
>* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置
|
||||
>* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置
|
||||
>* -f: 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json)
|
||||
|
||||
## 升级客户端
|
||||
```
|
||||
# update local client
|
||||
openp2p update
|
||||
./openp2p update
|
||||
# update remote client
|
||||
curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password='
|
||||
```
|
||||
@@ -38,4 +47,9 @@ Linux系统(Ubuntu和CentOS7)的防火墙默认配置均不会有影响,
|
||||
systemctl stop firewalld.service
|
||||
systemctl start firewalld.service
|
||||
firewall-cmd --state
|
||||
```
|
||||
|
||||
## 卸载
|
||||
```
|
||||
./openp2p uninstall
|
||||
```
|
||||
51
USAGE.md
@@ -1,33 +1,43 @@
|
||||
# Parameters details
|
||||
|
||||
## Listen
|
||||
> :warning: all commands in this doc, Windows env uses "openp2p.exe", Linux env uses "./openp2p"
|
||||
|
||||
|
||||
## Install and Listen
|
||||
```
|
||||
openp2p.exe -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
./openp2p install -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
Or
|
||||
./openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1
|
||||
|
||||
```
|
||||
>* -d daemon mode is recommand. 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
|
||||
>* -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
|
||||
>* -loglevel Need to view more debug logs, set 0; the default is 1
|
||||
>* -noshare 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
|
||||
>* 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
|
||||
>* -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
|
||||
>* -loglevel: Need to view more debug logs, set 0; the default is 1
|
||||
>* -noshare: 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
|
||||
|
||||
## Connect
|
||||
```
|
||||
openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
./openp2p -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 -peernode OFFICEPC1 -dstip 127.0.0.1 -dstport 3389 -srcport 23389 -protocol tcp
|
||||
Create multiple P2PApp by config file
|
||||
./openp2p -d -f
|
||||
./openp2p -f
|
||||
```
|
||||
>* -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
|
||||
>* -f Configuration file, if you want to configure multiple P2PApp refer to [config.json](/config.json)
|
||||
>* -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
|
||||
>* -f: Configuration file, if you want to configure multiple P2PApp refer to [config.json](/config.json)
|
||||
|
||||
## Client update
|
||||
```
|
||||
# update local client
|
||||
openp2p update
|
||||
./openp2p update
|
||||
# update remote client
|
||||
curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password='
|
||||
```
|
||||
@@ -38,4 +48,9 @@ The default firewall configuration of Linux system (Ubuntu and CentOS7) will not
|
||||
systemctl stop firewalld.service
|
||||
systemctl start firewalld.service
|
||||
firewall-cmd --state
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
```
|
||||
./openp2p uninstall
|
||||
```
|
||||
49
common.go
@@ -1,10 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getmac(ip string) string {
|
||||
@@ -99,3 +105,46 @@ func decryptBytes(key []byte, out, in []byte, dataLen int) ([]byte, error) {
|
||||
mode.CryptBlocks(out[:dataLen], in[:dataLen])
|
||||
return pkcs7UnPadding(out, dataLen)
|
||||
}
|
||||
|
||||
// {240e:3b7:622:3440:59ad:7fa1:170c:ef7f 47924975352157270363627191692449083263 China CN 0xc0000965c8 Guangdong GD 0 Guangzhou 23.1167 113.25 Asia/Shanghai AS4134 Chinanet }
|
||||
func netInfo() *NetInfo {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
// DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
// var d net.Dialer
|
||||
// return d.DialContext(ctx, "tcp6", addr)
|
||||
// },
|
||||
}
|
||||
// sometime will be failed, retry
|
||||
for i := 0; i < 2; i++ {
|
||||
client := &http.Client{Transport: tr, Timeout: time.Second * 10}
|
||||
r, err := client.Get("https://ifconfig.co/json")
|
||||
if err != nil {
|
||||
gLog.Println(LevelINFO, "netInfo error:", err)
|
||||
continue
|
||||
}
|
||||
defer r.Body.Close()
|
||||
buf := make([]byte, 1024*64)
|
||||
n, err := r.Body.Read(buf)
|
||||
if err != nil {
|
||||
gLog.Println(LevelINFO, "netInfo error:", err)
|
||||
continue
|
||||
}
|
||||
rsp := NetInfo{}
|
||||
err = json.Unmarshal(buf[:n], &rsp)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong NetInfo:%s", err)
|
||||
continue
|
||||
}
|
||||
return &rsp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func execOutput(name string, args ...string) string {
|
||||
cmdGetOsName := exec.Command(name, args...)
|
||||
var cmdOut bytes.Buffer
|
||||
cmdGetOsName.Stdout = &cmdOut
|
||||
cmdGetOsName.Run()
|
||||
return cmdOut.String()
|
||||
}
|
||||
|
||||
@@ -39,3 +39,7 @@ func TestAESCBC(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNetInfo(t *testing.T) {
|
||||
log.Println(netInfo())
|
||||
}
|
||||
|
||||
11
config.go
@@ -27,6 +27,7 @@ type AppConfig struct {
|
||||
shareBandwidth int
|
||||
}
|
||||
|
||||
// TODO: add loglevel, maxlogfilesize
|
||||
type Config struct {
|
||||
Network NetworkConfig `json:"network"`
|
||||
Apps []AppConfig `json:"apps"`
|
||||
@@ -45,10 +46,10 @@ func (c *Config) add(app AppConfig) {
|
||||
c.Apps = append(c.Apps, app)
|
||||
}
|
||||
|
||||
// func (c *Config) save() {
|
||||
// data, _ := json.MarshalIndent(c, "", "")
|
||||
// ioutil.WriteFile("config.json", data, 0644)
|
||||
// }
|
||||
func (c *Config) save() {
|
||||
data, _ := json.MarshalIndent(c, "", "")
|
||||
ioutil.WriteFile("config.json", data, 0644)
|
||||
}
|
||||
|
||||
func (c *Config) load() error {
|
||||
data, err := ioutil.ReadFile("config.json")
|
||||
@@ -76,7 +77,7 @@ type NetworkConfig struct {
|
||||
os string
|
||||
publicIP string
|
||||
natType int
|
||||
shareBandwidth int
|
||||
ShareBandwidth int
|
||||
// server info
|
||||
ServerHost string
|
||||
ServerPort int
|
||||
|
||||
22
config.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"network": {
|
||||
"Node": "hhd1207-222",
|
||||
"User": "tenderiron",
|
||||
"Password": "13760636579",
|
||||
"Node": "YOUR_NODE_NAME",
|
||||
"User": "YOUR_USER_NAME",
|
||||
"Password": "YOUR_PASSWORD",
|
||||
"ServerHost": "openp2p.cn",
|
||||
"ServerPort": 27182,
|
||||
"UDPPort1": 27182,
|
||||
@@ -11,21 +11,21 @@
|
||||
"apps": [
|
||||
{
|
||||
"Protocol": "tcp",
|
||||
"SrcPort": 53389,
|
||||
"PeerNode": "dell720-902",
|
||||
"DstPort": 3389,
|
||||
"DstHost": "10.1.6.36",
|
||||
"SrcPort": 22,
|
||||
"PeerNode": "YOURNODE1",
|
||||
"DstPort": 22,
|
||||
"DstHost": "127.0.0.1",
|
||||
"PeerUser": "",
|
||||
"PeerPassword": ""
|
||||
},
|
||||
{
|
||||
"Protocol": "tcp",
|
||||
"SrcPort": 22,
|
||||
"PeerNode": "dell720-902",
|
||||
"DstPort": 22,
|
||||
"SrcPort": 50022,
|
||||
"PeerNode": "YOURNODE2",
|
||||
"DstPort": 50022,
|
||||
"DstHost": "127.0.0.1",
|
||||
"PeerUser": "",
|
||||
"PeerPassword": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
197
daemon.go
@@ -1,16 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/kardianos/service"
|
||||
)
|
||||
|
||||
type daemon struct {
|
||||
running bool
|
||||
proc *os.Process
|
||||
}
|
||||
|
||||
func (d *daemon) Start(s service.Service) error {
|
||||
gLog.Println(LevelINFO, "daemon start")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *daemon) Stop(s service.Service) error {
|
||||
gLog.Println(LevelINFO, "service stop")
|
||||
d.running = false
|
||||
if d.proc != nil {
|
||||
gLog.Println(LevelINFO, "stop worker")
|
||||
d.proc.Kill()
|
||||
}
|
||||
if service.Interactive() {
|
||||
gLog.Println(LevelINFO, "stop daemon")
|
||||
os.Exit(0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *daemon) run() {
|
||||
gLog.Println(LevelINFO, "daemon start")
|
||||
defer gLog.Println(LevelINFO, "daemon end")
|
||||
gLog.Println(LevelINFO, "daemon run start")
|
||||
defer gLog.Println(LevelINFO, "daemon run end")
|
||||
os.Chdir(filepath.Dir(os.Args[0])) // for system service
|
||||
d.running = true
|
||||
binPath, _ := os.Executable()
|
||||
mydir, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
gLog.Println(LevelINFO, mydir)
|
||||
conf := &service.Config{
|
||||
Name: ProducnName,
|
||||
DisplayName: ProducnName,
|
||||
Description: ProducnName,
|
||||
Executable: binPath,
|
||||
}
|
||||
|
||||
s, _ := service.New(d, conf)
|
||||
go s.Run()
|
||||
var args []string
|
||||
// rm -d parameter
|
||||
for i := 0; i < len(os.Args); i++ {
|
||||
@@ -24,13 +68,160 @@ func (d *daemon) run() {
|
||||
// start worker
|
||||
gLog.Println(LevelINFO, "start worker process")
|
||||
execSpec := &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}}
|
||||
p, err := os.StartProcess(os.Args[0], args, execSpec)
|
||||
p, err := os.StartProcess(binPath, args, execSpec)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "start worker error:%s", err)
|
||||
return
|
||||
}
|
||||
d.proc = p
|
||||
_, _ = p.Wait()
|
||||
if !d.running {
|
||||
return
|
||||
}
|
||||
gLog.Printf(LevelERROR, "worker stop, restart it after 10s")
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *daemon) Control(ctrlComm string, exeAbsPath string, args []string) error {
|
||||
svcConfig := &service.Config{
|
||||
Name: ProducnName,
|
||||
DisplayName: ProducnName,
|
||||
Description: ProducnName,
|
||||
Executable: exeAbsPath,
|
||||
Arguments: args,
|
||||
}
|
||||
|
||||
s, e := service.New(d, svcConfig)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
e = service.Control(s, ctrlComm)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// examples:
|
||||
// listen:
|
||||
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -noshare
|
||||
// listen and build p2papp:
|
||||
// ./openp2p install -node hhd1207-222 -user tenderiron -password 13760636579 -noshare -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)
|
||||
// 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")
|
||||
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 ")
|
||||
protocol := installFlag.String("protocol", "tcp", "tcp or udp")
|
||||
noShare := installFlag.Bool("noshare", false, "disable using the huge numbers of shared nodes in OpenP2P network, your connectivity will be weak. also this node will not shared with others")
|
||||
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)
|
||||
gConf.Network.ServerHost = *serverHost
|
||||
gConf.Network.User = *user
|
||||
gConf.Network.Node = *node
|
||||
gConf.Network.Password = *password
|
||||
gConf.Network.ServerPort = 27182
|
||||
gConf.Network.UDPPort1 = 27182
|
||||
gConf.Network.UDPPort2 = 27183
|
||||
gConf.Network.NoShare = *noShare
|
||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||
config := AppConfig{}
|
||||
config.PeerNode = *peerNode
|
||||
config.PeerUser = *peerUser
|
||||
config.PeerPassword = *peerPassword
|
||||
config.DstHost = *dstIP
|
||||
config.DstPort = *dstPort
|
||||
config.SrcPort = *srcPort
|
||||
config.Protocol = *protocol
|
||||
gConf.add(config)
|
||||
os.Chdir(defaultInstallPath)
|
||||
gConf.save()
|
||||
|
||||
// copy files
|
||||
os.MkdirAll(defaultInstallPath, 0775)
|
||||
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 {
|
||||
gLog.Printf(LevelERROR, "os.OpenFile %s error:%s", os.Args[0], errFiles)
|
||||
return
|
||||
}
|
||||
|
||||
dst, errFiles := os.OpenFile(targetPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0775)
|
||||
if errFiles != nil {
|
||||
gLog.Printf(LevelERROR, "os.OpenFile %s error:%s", targetPath, errFiles)
|
||||
return
|
||||
}
|
||||
|
||||
_, errFiles = io.Copy(dst, src)
|
||||
if errFiles != nil {
|
||||
gLog.Printf(LevelERROR, "io.Copy error:%s", errFiles)
|
||||
return
|
||||
}
|
||||
src.Close()
|
||||
dst.Close()
|
||||
|
||||
// install system service
|
||||
d := daemon{}
|
||||
|
||||
// args := []string{""}
|
||||
gLog.Println(LevelINFO, "targetPath:", targetPath)
|
||||
err := d.Control("install", targetPath, []string{"-d", "-f"})
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "install system service error:", err)
|
||||
} else {
|
||||
gLog.Println(LevelINFO, "install system service ok.")
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
err = d.Control("start", targetPath, []string{"-d", "-f"})
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "start openp2p service error:", err)
|
||||
} else {
|
||||
gLog.Println(LevelINFO, "start openp2p service ok.")
|
||||
}
|
||||
}
|
||||
|
||||
func uninstall() {
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p-install", LevelDEBUG, 1024*1024, LogFileAndConsole)
|
||||
d := daemon{}
|
||||
d.Control("stop", "", nil)
|
||||
err := d.Control("uninstall", "", nil)
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "uninstall system service error:", err)
|
||||
} else {
|
||||
gLog.Println(LevelINFO, "uninstall system service ok.")
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
1
go.mod
@@ -4,6 +4,7 @@ go 1.16
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/kardianos/service v1.2.0
|
||||
github.com/lucas-clemente/quic-go v0.24.0
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34
|
||||
)
|
||||
|
||||
21
log.go
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -55,7 +54,6 @@ type V8log struct {
|
||||
stoped bool
|
||||
lineEnding string
|
||||
pid int
|
||||
lastError string
|
||||
maxLogSize int64
|
||||
mode int
|
||||
}
|
||||
@@ -89,7 +87,7 @@ func InitLogger(path string, filePrefix string, level LogLevel, maxLogSize int64
|
||||
} else {
|
||||
le = "\n"
|
||||
}
|
||||
pLog := &V8log{logger, openedfile, level, make(chan bool, 10), logdir, &sync.Mutex{}, false, le, os.Getpid(), "", maxLogSize, mode}
|
||||
pLog := &V8log{logger, openedfile, level, make(chan bool, 10), logdir, &sync.Mutex{}, false, le, os.Getpid(), maxLogSize, mode}
|
||||
go pLog.checkFile()
|
||||
return pLog
|
||||
}
|
||||
@@ -155,15 +153,11 @@ func (vl *V8log) Printf(level LogLevel, format string, params ...interface{}) {
|
||||
if level < vl.llevel {
|
||||
return
|
||||
}
|
||||
if level == LevelERROR {
|
||||
vl.lastError = fmt.Sprintf(format, params...)
|
||||
}
|
||||
pidAndLevel := []interface{}{vl.pid, loglevel[level]}
|
||||
params = append(pidAndLevel, params...)
|
||||
if vl.mode == LogFile || vl.mode == LogFileAndConsole {
|
||||
vl.loggers[0].Printf("%d %s "+format+vl.lineEnding, params...)
|
||||
}
|
||||
|
||||
if vl.mode == LogConsole || vl.mode == LogFileAndConsole {
|
||||
log.Printf("%d %s "+format+vl.lineEnding, params...)
|
||||
}
|
||||
@@ -179,20 +173,13 @@ func (vl *V8log) Println(level LogLevel, params ...interface{}) {
|
||||
if level < vl.llevel {
|
||||
return
|
||||
}
|
||||
if level == LevelERROR {
|
||||
vl.lastError = fmt.Sprint(params...)
|
||||
}
|
||||
pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "}
|
||||
params = append(pidAndLevel, params...)
|
||||
params = append(params, vl.lineEnding)
|
||||
vl.loggers[0].Print(params...)
|
||||
if vl.mode == LogFile || vl.mode == LogFileAndConsole {
|
||||
vl.loggers[0].Print(params...)
|
||||
}
|
||||
if vl.mode == LogConsole || vl.mode == LogFileAndConsole {
|
||||
log.Print(params...)
|
||||
}
|
||||
}
|
||||
|
||||
func (vl *V8log) getLastError() string {
|
||||
vl.mtx.Lock()
|
||||
defer vl.mtx.Unlock()
|
||||
return vl.lastError
|
||||
}
|
||||
|
||||
50
nat.go
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func natTest(serverHost string, serverPort int, localPort int) (publicIP string, isPublicIP int, publicPort int, err error) {
|
||||
func natTest(serverHost string, serverPort int, localPort int, echoPort int) (publicIP string, isPublicIP int, publicPort int, err error) {
|
||||
conn, err := net.ListenPacket("udp", fmt.Sprintf(":%d", localPort))
|
||||
if err != nil {
|
||||
return "", 0, 0, err
|
||||
@@ -21,7 +21,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, &NatDetectReq{SrcPort: localPort, EchoPort: EchoPort})
|
||||
msg, err := newMessage(MsgNATDetect, 0, &NatDetectReq{SrcPort: localPort, EchoPort: echoPort})
|
||||
_, err = conn.WriteTo(msg, dst)
|
||||
if err != nil {
|
||||
return "", 0, 0, err
|
||||
@@ -39,14 +39,44 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
|
||||
}
|
||||
natRsp := NatDetectRsp{}
|
||||
err = json.Unmarshal(buffer[openP2PHeaderSize:nRead], &natRsp)
|
||||
|
||||
// testing for public ip
|
||||
if echoPort != 0 {
|
||||
for {
|
||||
gLog.Printf(LevelINFO, "public ip test start %s:%d", natRsp.IP, echoPort)
|
||||
conn, err := net.ListenUDP("udp", nil)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
defer conn.Close()
|
||||
dst, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", natRsp.IP, echoPort))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
conn.WriteTo([]byte("echo"), dst)
|
||||
buf := make([]byte, 1600)
|
||||
|
||||
// wait for echo testing
|
||||
conn.SetReadDeadline(time.Now().Add(PublicIPEchoTimeout))
|
||||
_, _, err = conn.ReadFromUDP(buf)
|
||||
if err == nil {
|
||||
gLog.Println(LevelINFO, "public ip:YES")
|
||||
natRsp.IsPublicIP = 1
|
||||
} else {
|
||||
gLog.Println(LevelINFO, "public ip:NO")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return natRsp.IP, natRsp.IsPublicIP, natRsp.Port, nil
|
||||
}
|
||||
|
||||
func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, err error) {
|
||||
// the random local port may be used by other.
|
||||
go echo()
|
||||
localPort := int(rand.Uint32()%10000 + 50000)
|
||||
ip1, isPublicIP, port1, err := natTest(host, udp1, localPort)
|
||||
echoPort := int(rand.Uint32()%10000 + 50000)
|
||||
go echo(echoPort)
|
||||
ip1, isPublicIP, port1, err := natTest(host, udp1, localPort, echoPort)
|
||||
gLog.Printf(LevelDEBUG, "local port:%d nat port:%d", localPort, port1)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
@@ -54,7 +84,7 @@ func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int,
|
||||
if isPublicIP == 1 {
|
||||
return ip1, NATNone, nil
|
||||
}
|
||||
ip2, _, port2, err := natTest(host, udp2, localPort)
|
||||
ip2, _, port2, err := natTest(host, udp2, localPort, 0) // 2rd nat test not need testing publicip
|
||||
gLog.Printf(LevelDEBUG, "local port:%d nat port:%d", localPort, port2)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
@@ -70,14 +100,8 @@ func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int,
|
||||
return ip1, natType, nil
|
||||
}
|
||||
|
||||
const (
|
||||
UDPPort1 = 27182
|
||||
UDPPort2 = 27183
|
||||
EchoPort = 31415
|
||||
)
|
||||
|
||||
func echo() {
|
||||
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: EchoPort})
|
||||
func echo(echoPort int) {
|
||||
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: echoPort})
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "echo server listen error:", err)
|
||||
return
|
||||
|
||||
40
openp2p.go
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
// 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 {
|
||||
@@ -19,12 +20,27 @@ func main() {
|
||||
fmt.Println(OpenP2PVersion)
|
||||
return
|
||||
case "update":
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LevelDEBUG, 1024*1024, LogConsole)
|
||||
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, []string{"-d", "-f"})
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "restart service error:", err)
|
||||
} else {
|
||||
gLog.Println(LevelINFO, "restart service ok.")
|
||||
}
|
||||
return
|
||||
case "install":
|
||||
install()
|
||||
return
|
||||
case "uninstall":
|
||||
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")
|
||||
@@ -32,8 +48,6 @@ func main() {
|
||||
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 ")
|
||||
serverHost := flag.String("serverhost", "openp2p.cn", "server host ")
|
||||
// serverHost := flag.String("serverhost", "127.0.0.1", "server host ") // for debug
|
||||
dstPort := flag.Int("dstport", 0, "destination port ")
|
||||
srcPort := flag.Int("srcport", 0, "source port ")
|
||||
protocol := flag.String("protocol", "tcp", "tcp or udp")
|
||||
@@ -44,7 +58,8 @@ func main() {
|
||||
byDaemon := flag.Bool("bydaemon", false, "start by daemon")
|
||||
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||
flag.Parse()
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LogLevel(*logLevel), 1024*1024, LogConsole)
|
||||
|
||||
gLog = InitLogger(filepath.Dir(os.Args[0]), "openp2p", LogLevel(*logLevel), 1024*1024, LogFileAndConsole)
|
||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||
if *daemonMode {
|
||||
d := daemon{}
|
||||
@@ -53,18 +68,7 @@ func main() {
|
||||
}
|
||||
if !*configFile {
|
||||
// validate cmd params
|
||||
if *node == "" {
|
||||
gLog.Println(LevelERROR, "node name not set", os.Args, len(os.Args), os.Args[0])
|
||||
return
|
||||
}
|
||||
if *user == "" {
|
||||
gLog.Println(LevelERROR, "user name not set")
|
||||
return
|
||||
}
|
||||
if *password == "" {
|
||||
gLog.Println(LevelERROR, "password not set")
|
||||
return
|
||||
}
|
||||
checkParams(*node, *user, *password)
|
||||
if *peerNode != "" {
|
||||
if *dstPort == 0 {
|
||||
gLog.Println(LevelERROR, "dstPort not set")
|
||||
@@ -103,7 +107,7 @@ func main() {
|
||||
UDPPort1: 27182,
|
||||
UDPPort2: 27183,
|
||||
ipv6: "240e:3b7:621:def0:fda4:dd7f:36a1:2803", // TODO: detect real ipv6
|
||||
shareBandwidth: *shareBandwidth,
|
||||
ShareBandwidth: *shareBandwidth,
|
||||
}
|
||||
}
|
||||
// gConf.save() // not change config file
|
||||
|
||||
@@ -24,6 +24,9 @@ type p2pApp struct {
|
||||
}
|
||||
|
||||
func (app *p2pApp) isActive() bool {
|
||||
if app.tunnel == nil {
|
||||
return false
|
||||
}
|
||||
if app.rtid == 0 { // direct mode app heartbeat equals to tunnel heartbeat
|
||||
return app.tunnel.isActive()
|
||||
}
|
||||
@@ -119,7 +122,9 @@ func (app *p2pApp) close() {
|
||||
if app.listener != nil {
|
||||
app.listener.Close()
|
||||
}
|
||||
app.tunnel.closeOverlayConns(app.id)
|
||||
if app.tunnel != nil {
|
||||
app.tunnel.closeOverlayConns(app.id)
|
||||
}
|
||||
app.wg.Wait()
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -30,7 +30,8 @@ type P2PNetwork struct {
|
||||
restartCh chan bool
|
||||
wg sync.WaitGroup
|
||||
writeMtx sync.Mutex
|
||||
serverTs uint64
|
||||
serverTs int64
|
||||
localTs int64
|
||||
// msgMap sync.Map
|
||||
msgMap map[uint64]chan []byte //key: nodeID
|
||||
msgMapMtx sync.Mutex
|
||||
@@ -48,7 +49,7 @@ func P2PNetworkInstance(config *NetworkConfig) *P2PNetwork {
|
||||
online: false,
|
||||
running: true,
|
||||
msgMap: make(map[uint64]chan []byte),
|
||||
limiter: newBandwidthLimiter(config.shareBandwidth),
|
||||
limiter: newBandwidthLimiter(config.ShareBandwidth),
|
||||
}
|
||||
instance.msgMap[0] = make(chan []byte) // for gateway
|
||||
if config != nil {
|
||||
@@ -105,10 +106,6 @@ func (pn *P2PNetwork) autoReconnectApp() {
|
||||
thisRound := make([]AppConfig, 0)
|
||||
for i := 0; i < len(retryApps); i++ {
|
||||
// reset retryNum when running 15min continuously
|
||||
delay := math.Exp(float64(retryApps[i].retryNum+1)/2) * 5
|
||||
if delay > 1800 { // max delay 30min
|
||||
delay = 1800
|
||||
}
|
||||
if retryApps[i].retryTime.Add(time.Minute * 15).Before(time.Now()) {
|
||||
retryApps[i].retryNum = 0
|
||||
}
|
||||
@@ -150,7 +147,7 @@ func (pn *P2PNetwork) autoReconnectApp() {
|
||||
func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint64) (*P2PTunnel, uint64, error) {
|
||||
gLog.Printf(LevelINFO, "addRelayTunnel to %s start", config.PeerNode)
|
||||
defer gLog.Printf(LevelINFO, "addRelayTunnel to %s end", config.PeerNode)
|
||||
pn.write(MsgRelay, MsgRelayNodeReq, nil)
|
||||
pn.write(MsgRelay, MsgRelayNodeReq, &RelayNodeReq{config.PeerNode})
|
||||
head, body := pn.read("", MsgRelay, MsgRelayNodeRsp, time.Second*10)
|
||||
if head == nil {
|
||||
return nil, 0, errors.New("read MsgRelayNodeRsp error")
|
||||
@@ -253,14 +250,11 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
PeerUser: config.PeerUser,
|
||||
PeerNatType: peerNatType,
|
||||
PeerIP: peerIP,
|
||||
ShareBandwidth: pn.config.shareBandwidth,
|
||||
ShareBandwidth: pn.config.ShareBandwidth,
|
||||
RelayNode: relayNode,
|
||||
Version: OpenP2PVersion,
|
||||
}
|
||||
pn.write(MsgReport, MsgReportConnect, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app := p2pApp{
|
||||
id: appID,
|
||||
@@ -270,7 +264,9 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
|
||||
rtid: rtid,
|
||||
hbTime: time.Now()}
|
||||
pn.apps.Store(appID, &app)
|
||||
go app.listen()
|
||||
if err == nil {
|
||||
go app.listen()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -377,7 +373,7 @@ func (pn *P2PNetwork) init() error {
|
||||
// detect nat type
|
||||
pn.config.publicIP, pn.config.natType, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2)
|
||||
// TODO rm test s2s
|
||||
if pn.config.Node == "hhd1207-222S2S" {
|
||||
if strings.Contains(pn.config.Node, "openp2pS2STest") {
|
||||
pn.config.natType = NATSymmetric
|
||||
}
|
||||
if err != nil {
|
||||
@@ -396,7 +392,6 @@ func (pn *P2PNetwork) init() error {
|
||||
q.Add("password", pn.config.Password)
|
||||
q.Add("version", OpenP2PVersion)
|
||||
q.Add("nattype", fmt.Sprintf("%d", pn.config.natType))
|
||||
q.Add("timestamp", fmt.Sprintf("%d", time.Now().Unix()))
|
||||
|
||||
noShareStr := "false"
|
||||
if pn.config.NoShare {
|
||||
@@ -422,13 +417,22 @@ func (pn *P2PNetwork) init() error {
|
||||
|
||||
pn.config.mac = getmac(pn.config.localIP)
|
||||
pn.config.os = getOsName()
|
||||
|
||||
req := ReportBasic{
|
||||
Mac: pn.config.mac,
|
||||
LanIP: pn.config.localIP,
|
||||
OS: pn.config.os,
|
||||
IPv6: pn.config.ipv6,
|
||||
Version: OpenP2PVersion,
|
||||
}
|
||||
rsp := netInfo()
|
||||
gLog.Println(LevelINFO, rsp)
|
||||
if rsp != nil && rsp.Country != "" {
|
||||
if len(rsp.IP) == net.IPv6len {
|
||||
pn.config.ipv6 = rsp.IP.String()
|
||||
req.IPv6 = rsp.IP.String()
|
||||
}
|
||||
req.NetInfo = *rsp
|
||||
}
|
||||
pn.write(MsgReport, MsgReportBasic, &req)
|
||||
gLog.Println(LevelINFO, "P2PNetwork init ok")
|
||||
break
|
||||
@@ -461,8 +465,9 @@ func (pn *P2PNetwork) handleMessage(t int, msg []byte) {
|
||||
gLog.Printf(LevelERROR, "login error:%d, detail:%s", rsp.Error, rsp.Detail)
|
||||
pn.running = false
|
||||
} else {
|
||||
gLog.Printf(LevelINFO, "login ok. Server ts=%d, local ts=%d", rsp.Ts, time.Now().Unix())
|
||||
pn.serverTs = rsp.Ts
|
||||
pn.localTs = time.Now().Unix()
|
||||
gLog.Printf(LevelINFO, "login ok. Server ts=%d, local ts=%d", rsp.Ts, pn.localTs)
|
||||
}
|
||||
case MsgHeartbeat:
|
||||
gLog.Printf(LevelDEBUG, "P2PNetwork heartbeat ok")
|
||||
@@ -605,7 +610,9 @@ func (pn *P2PNetwork) handlePush(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()) || (req.User == pn.config.User && req.Password == pn.config.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) {
|
||||
gLog.Printf(LevelINFO, "Access Granted\n")
|
||||
config := AppConfig{}
|
||||
config.peerNatType = req.NatType
|
||||
@@ -614,8 +621,8 @@ func (pn *P2PNetwork) handlePush(subType uint16, msg []byte) error {
|
||||
config.PeerNode = req.From
|
||||
// share relay node will limit bandwidth
|
||||
if req.User != pn.config.User || req.Password != pn.config.Password {
|
||||
gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.shareBandwidth)
|
||||
config.shareBandwidth = pn.config.shareBandwidth
|
||||
gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
|
||||
config.shareBandwidth = pn.config.ShareBandwidth
|
||||
}
|
||||
// go pn.AddTunnel(config, req.ID)
|
||||
go pn.addDirectTunnel(config, req.ID)
|
||||
|
||||
@@ -39,7 +39,7 @@ func (t *P2PTunnel) init() {
|
||||
localPort := int(rand.Uint32()%10000 + 50000)
|
||||
if t.pn.config.natType == NATCone {
|
||||
// prepare one random cone hole
|
||||
_, _, port1, _ := natTest(t.pn.config.ServerHost, t.pn.config.UDPPort1, localPort)
|
||||
_, _, port1, _ := natTest(t.pn.config.ServerHost, t.pn.config.UDPPort1, localPort, 0)
|
||||
t.coneLocalPort = localPort
|
||||
t.coneNatPort = port1
|
||||
t.la = &net.UDPAddr{IP: net.ParseIP(t.pn.config.localIP), Port: t.coneLocalPort}
|
||||
|
||||
42
protocol.go
@@ -6,10 +6,12 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"hash/crc64"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
const OpenP2PVersion = "0.95.5"
|
||||
const OpenP2PVersion = "0.97.0"
|
||||
const ProducnName string = "openp2p"
|
||||
|
||||
type openP2PHeader struct {
|
||||
@@ -125,7 +127,7 @@ const (
|
||||
AESKeySize = 16
|
||||
MaxRetry = 10
|
||||
RetryInterval = time.Second * 30
|
||||
PublicIPEchoTimeout = time.Second * 5
|
||||
PublicIPEchoTimeout = time.Second * 3
|
||||
NatTestTimeout = time.Second * 10
|
||||
)
|
||||
|
||||
@@ -196,7 +198,7 @@ type PushRsp struct {
|
||||
type LoginRsp struct {
|
||||
Error int `json:"error,omitempty"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
Ts uint64 `json:"ts,omitempty"`
|
||||
Ts int64 `json:"ts,omitempty"`
|
||||
}
|
||||
|
||||
type NatDetectReq struct {
|
||||
@@ -231,6 +233,10 @@ type TunnelMsg struct {
|
||||
ID uint64 `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
type RelayNodeReq struct {
|
||||
PeerNode string `json:"peerNode,omitempty"`
|
||||
}
|
||||
|
||||
type RelayNodeRsp struct {
|
||||
RelayName string `json:"relayName,omitempty"`
|
||||
RelayToken uint64 `json:"relayToken,omitempty"`
|
||||
@@ -250,11 +256,12 @@ type RelayHeartbeat struct {
|
||||
}
|
||||
|
||||
type ReportBasic struct {
|
||||
OS string `json:"os,omitempty"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
LanIP string `json:"lanIP,omitempty"`
|
||||
IPv6 string `json:"IPv6,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
OS string `json:"os,omitempty"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
LanIP string `json:"lanIP,omitempty"`
|
||||
IPv6 string `json:"IPv6,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
NetInfo NetInfo `json:"netInfo,omitempty"`
|
||||
}
|
||||
|
||||
type ReportConnect struct {
|
||||
@@ -278,3 +285,22 @@ type UpdateInfo struct {
|
||||
ErrorDetail string `json:"errorDetail,omitempty"`
|
||||
Url string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
type NetInfo struct {
|
||||
IP net.IP `json:"ip"`
|
||||
IPDecimal *big.Int `json:"ip_decimal"`
|
||||
Country string `json:"country,omitempty"`
|
||||
CountryISO string `json:"country_iso,omitempty"`
|
||||
CountryEU *bool `json:"country_eu,omitempty"`
|
||||
RegionName string `json:"region_name,omitempty"`
|
||||
RegionCode string `json:"region_code,omitempty"`
|
||||
MetroCode uint `json:"metro_code,omitempty"`
|
||||
PostalCode string `json:"zip_code,omitempty"`
|
||||
City string `json:"city,omitempty"`
|
||||
Latitude float64 `json:"latitude,omitempty"`
|
||||
Longitude float64 `json:"longitude,omitempty"`
|
||||
Timezone string `json:"time_zone,omitempty"`
|
||||
ASN string `json:"asn,omitempty"`
|
||||
ASNOrg string `json:"asn_org,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultInstallPath = "/usr/local/openp2p"
|
||||
defaultBinName = "openp2p"
|
||||
)
|
||||
|
||||
func getOsName() (osName string) {
|
||||
output := execOutput("sw_vers", "-productVersion")
|
||||
osName = "Mac OS X " + strings.TrimSpace(output)
|
||||
|
||||
@@ -12,6 +12,11 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultInstallPath = "/usr/local/openp2p"
|
||||
defaultBinName = "openp2p"
|
||||
)
|
||||
|
||||
func getOsName() (osName string) {
|
||||
var sysnamePath string
|
||||
sysnamePath = "/etc/redhat-release"
|
||||
|
||||
@@ -13,6 +13,11 @@ import (
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultInstallPath = "C:\\Program Files\\OpenP2P"
|
||||
defaultBinName = "openp2p.exe"
|
||||
)
|
||||
|
||||
func getOsName() (osName string) {
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE|registry.WOW64_64KEY)
|
||||
if err != nil {
|
||||
|
||||