Compare commits

...
15 Commits
Author SHA1 Message Date
TenderIronh a528441342 install error 2021-12-21 14:41:07 +08:00
TenderIronh 2d6521be43 update readme 2021-12-15 15:42:27 +08:00
TenderIronh 2223634c83 update readme 2021-12-15 15:41:39 +08:00
TenderIronh 6c1551d951 auto adjust server and local timestamp for totp 2021-12-14 15:25:38 +08:00
TenderIronh dd3d87c3d2 update doc 2021-12-13 18:31:31 +08:00
TenderIronh a28fc33b66 fix nil pointer and testing public ip 2021-12-10 17:20:17 +08:00
TenderIronh f12059d889 install mode and improve relay 2021-12-09 18:54:46 +08:00
TenderIronh a2387fed68 fix build darwin 2021-12-09 11:26:59 +08:00
hhd 8353c1c3dd ifconfig retry 2021-12-01 18:00:23 +08:00
hhd a9250737f1 report netinfo, improve relay model 2021-12-01 16:08:44 +08:00
hhd c83a57f014 goal and principle for free 2021-11-30 15:57:41 +08:00
hhd 8551264a15 no weibo wechat 2021-11-25 18:08:05 +08:00
hhd 1ef0f919d9 lower case png 2021-11-25 18:03:56 +08:00
hhd f01ca64dd9 readme 2021-11-25 11:00:17 +08:00
hhd c6f50992c3 readme 2021-11-24 22:53:46 +08:00
28 changed files with 590 additions and 219 deletions
+45 -35
View File
@@ -1,39 +1,54 @@
[English](/README.md)|中文 # [English](/README.md)|中文
网站: [openp2p.cn](https://openp2p.cn)
## OpenP2P是什么 ## OpenP2P是什么
它是一个开源、免费、轻量级的P2P共享网络。任何设备接入OpenP2P,就可以随时随地访问它们。 它是一个开源、免费、轻量级的P2P共享网络。任何设备接入OpenP2P,随时随地访问它们。相比BT网络用来共享文件,OpenP2P网络用来共享带宽。
我们的目标是:充分利用带宽,利用共享节点转发数据,建设一个远程连接的通用基础设施。
## 为什么选择OpenP2P ## 为什么选择OpenP2P
### 免费 ### 1. 免费
完全免费,满足大部分用户的核心白票需求。不像其它类似的产品,我们不需要有公网IP的服务器,不需要花钱买服务。 完全免费,满足大部分用户的核心白票需求。不像其它类似的产品,OpenP2P不需要有公网IP的服务器,不需要花钱买服务。了解它原理即可理解为什么能做到免费。
### 安全 ### 2. 共享
代码开源,接受各位大佬检验。下面详细展开 你的设备会形成一个私有P2P网络,它们之间共享带宽,提供网络数据转发服务。
### 轻量 当你的私有P2P网络下没有可以提供转发服务的节点时,会尝试在公共P2P网络寻找转发节点。
默认会开启共享限速10mbps,只有你用户下提供了共享节点才能使用别人的共享节点。这非常公平,也是这个项目的初衷。
我们建议你在带宽足够的地方(比如办公室,家里的百兆光纤)加入共享网络。
如果你不想共享任何节点,或设置共享带宽,请查看[详细使用说明](/USAGE-ZH.md)
### 3. 安全
代码开源,P2P隧道使用TLS1.3+AES双重加密,共享节点临时授权使用TOTP一次性密码
[查看详细](#安全性)
### 4. 轻量
文件大小2MB+,运行内存2MB+;全部在应用层实现,没有虚拟网卡,没有内核程序 文件大小2MB+,运行内存2MB+;全部在应用层实现,没有虚拟网卡,没有内核程序
### 跨平台 ### 5. 跨平台
因为轻量,所以很容易支持各个平台。支持主流的操作系统:Windows,Linux,MacOS;和主流的cpu架构:386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64 因为轻量,所以很容易支持各个平台。支持主流的操作系统:Windows,Linux,MacOS;和主流的cpu架构:386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64
### 高效 ### 6. 高效
P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络环境,无论NAT1-4(Cone或Symmetric),都支持。依靠Quic协议优秀的拥塞算法,能在糟糕的网络环境获得高带宽低延时。 P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络环境,无论NAT1-4(Cone或Symmetric),都支持。依靠Quic协议优秀的拥塞算法,能在糟糕的网络环境获得高带宽低延时。
### 二次开发 ### 7. 二次开发
基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信 基于OpenP2P只需数行代码,就能让原来只能局域网通信的程序,变成任何内网都能通信
## 快速入门 ## 快速入门
> :warning: 本文所有命令, Windows环境使用"openp2p.exe", Linux环境使用"./openp2p"
以一个最常见的例子说明OpenP2P如何使用:远程办公,在家里连入办公室Windows电脑。 以一个最常见的例子说明OpenP2P如何使用:远程办公,在家里连入办公室Windows电脑。
相信很多人在疫情下远程办公是刚需。 相信很多人在疫情下远程办公是刚需。
1. 先确认办公室电脑已开启远程桌面功能(如何开启参考官方说明https://docs.microsoft.com/zh-cn/windows-server/remote/remote-desktop-services/clients/remote-desktop-allow-access 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个字符**
![image](/doc/images/officelisten.png) ![image](/doc/images/officelisten.png)
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 openp2p.exe -d -node HOMEPC123 -user USERNAME1 -password PASSWORD1 --peernode OFFICEPC1 --dstip 127.0.0.1 --dstport 3389 --srcport 23389 --protocol tcp
``` ```
`切记将标记大写的参数改成自己的` > :warning: **切记将标记大写的参数改成自己的**
![image](/doc/images/homeconnect.png) ![image](/doc/images/homeconnect.png)
![image](/doc/images/mem.png) ![image](/doc/images/mem.png)
`LISTEN ON PORT 23389 START` 看到这行日志表示P2PApp建立成功,监听23389端口。只需连接本机的127.0.0.1:23389就相当于连接公司Windows电脑的3389端口。 `LISTEN ON PORT 23389 START` 看到这行日志表示P2PApp建立成功,监听23389端口。只需连接本机的127.0.0.1:23389就相当于连接公司Windows电脑的3389端口。
@@ -43,16 +58,17 @@ P2P直连可以让你的设备跑满带宽。不论你的设备在任何网络
![image](/doc/images/afterconnect.png) ![image](/doc/images/afterconnect.png)
## [详细使用说明](/USAGE-ZH.md) ## 详细使用说明
[这里](/USAGE-ZH.md)详细介绍如何使用和运行参数
## 典型应用场景 ## 典型应用场景
特别适合大流量的内网访问 特别适合大流量的内网访问
### 远程办公 >* 远程办公: Windows MSTSC、VNC等远程桌面,SSH,内网各种ERP系统
Windows MSTSC、VNC等远程桌面,SSH,内网各种ERP系统 >* 远程访问内网ERP系统
### 远程访问NAS >* 远程访问NAS: 管理大量视频、图片
管理大量视频、图片 >* 远程监控摄像头
### 远程监控摄像头 >* 远程刷机
### 远程刷机 >* 远程数据备份
### 远程数据备份
--- ---
## 概要设计 ## 概要设计
### 原型 ### 原型
@@ -62,18 +78,14 @@ Windows MSTSC、VNC等远程桌面,SSH,内网各种ERP系统
### P2PApp ### P2PApp
它是项目里最重要的概念,一个P2PApp就是把远程的一个服务(mstsc/ssh等)通过P2P网络映射到本地监听。二次开发或者我们提供的Restful API,主要工作就是管理P2PApp 它是项目里最重要的概念,一个P2PApp就是把远程的一个服务(mstsc/ssh等)通过P2P网络映射到本地监听。二次开发或者我们提供的Restful API,主要工作就是管理P2PApp
![image](/doc/images/appdetail.png) ![image](/doc/images/appdetail.png)
## 共享
默认会开启共享限速10mbps,只有你用户下提供了共享节点才能使用别人的共享节点。这非常公平,也是这个项目的初衷。
我们建议你在带宽足够的地方(比如办公室,家里的百兆光纤)加入共享网络。
如果你仍然不想共享任何节点,请查看运行参数
## 安全性 ## 安全性
加入OpenP2P共享网络的节点,只能凭授权访问。共享节点只会中转数据,别人无法访问内网任何资源。 加入OpenP2P共享网络的节点,只能凭授权访问。共享节点只会中转数据,别人无法访问内网任何资源。
### TLS1.3+AES ### 1. TLS1.3+AES
两个节点间通信数据走业界最安全的TLS1.3通道。通信内容还会使用AES加密,双重安全,密钥是通过服务端作换。有效阻止中间人攻击 两个节点间通信数据走业界最安全的TLS1.3通道。通信内容还会使用AES加密,双重安全,密钥是通过服务端作换。有效阻止中间人攻击
### 共享的中转节点是否会获得我的数据 ### 2. 共享的中转节点是否会获得我的数据
没错,中转节点天然就是一个中间人,所以才加上AES加密通信内容保证安全。中转节点是无法获取明文的 没错,中转节点天然就是一个中间人,所以才加上AES加密通信内容保证安全。中转节点是无法获取明文的
### 中转节点是如何校验权限的 ### 3. 中转节点是如何校验权限的
服务端有个调度模型,根据带宽、ping值、稳定性、服务时长,尽可能地使共享节点均匀地提供服务。连接共享节点使用TOTP密码,hmac-sha256算法校验,它是一次性密码,和我们平时使用的手机验证码或银行密码器一样的原理。 服务端有个调度模型,根据带宽、ping值、稳定性、服务时长,尽可能地使共享节点均匀地提供服务。连接共享节点使用TOTP密码,hmac-sha256算法校验,它是一次性密码,和我们平时使用的手机验证码或银行密码器一样的原理。
## 编译 ## 编译
@@ -102,7 +114,7 @@ go build
14. 内网直连优化,用处不大,估计就用户测试时用到 14. 内网直连优化,用处不大,估计就用户测试时用到
远期计划: 远期计划:
1. 彻底地分布式去中心化设计 1. 利用区块链技术去中心化,让共享设备的用户有收益,从而促进更多用户共享,达到正向闭环。
2. 企业级支持,可以更好地管理大量设备,和更安全更细的权限控制 2. 企业级支持,可以更好地管理大量设备,和更安全更细的权限控制
## 参与贡献 ## 参与贡献
@@ -111,9 +123,7 @@ TODO或ISSUE里如果有你擅长的领域,或者你有特别好的主意,
它是一个中国人发起的项目,更懂国内网络环境,更懂用户需求,更好的企业级支持 它是一个中国人发起的项目,更懂国内网络环境,更懂用户需求,更好的企业级支持
## 技术交流 ## 技术交流
QQ群:16947733 QQ群:16947733
邮箱:openp2p.cn@gmail.com 271357901@qq.com 邮箱:openp2p.cn@gmail.com tenderiron@139.com
第一时间获得最新版本消息,以及一些最新IT业界动态
微信公众号:openp2p
微博:https://weibo.com/openp2p
## 免责声明 ## 免责声明
本项目开源供大家学习和免费使用,禁止用于非法用途,任何不当使用本项目或意外造成的损失,本项目及相关人员不会承担任何责任。 本项目开源供大家学习和免费使用,禁止用于非法用途,任何不当使用本项目或意外造成的损失,本项目及相关人员不会承担任何责任。
+44 -37
View File
@@ -1,29 +1,41 @@
English|[中文](/README-ZH.md) # English|[中文](/README-ZH.md)
Website: [openp2p.cn](https://openp2p.cn)
## What is OpenP2P ## 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 ## Why OpenP2P
### Free ### 1. 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.
### 2. Share
Your devices will form a private P2P network, share bandwidth between them, and provide network data forwarding services.
When there is no node that can provide forwarding services in your private P2P network, you will try to find forwarding nodes in the public P2P network.
10mbps is its default setting of share speed limit. Only when you have shared their nodes, you 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 not willing to contribute any node to the OpenP2P share network, please refer to the [usage](/USAGE.md) for your own setting.
### 3. Safe
The code is open source, the P2P tunnel uses TLS1.3+AES double encryption, and the shared node temporarily authorizes the use of the TOTP one-time password
### Safe [details](#Safety)
Open source, trustable(see details below)
### Lightweight ### 4. Lightweight
2MB+ filesize, 2MB+ memory. It runs at appllication layer, no vitrual NIC, no kernel driver. 2MB+ filesize, 2MB+ memory. It runs at appllication layer, no vitrual NIC, no kernel driver.
### Cross-platform ### 5. Cross-platform
Benefit from lightweight, it easily supports most of major OS, like Windows, Linux, MacOS, also most of CPU architecture, like 386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64. Benefit from lightweight, it easily supports most of major OS, like Windows, Linux, MacOS, also most of CPU architecture, like 386、amd64、arm、arm64、mipsle、mipsle64、mips、mips64.
### Efficient ### 6. Efficient
P2P direct connection lets your devices make good use of bandwidth. Your device can be connected in any network environments, even supports NAT1-4 (Cone or Symmetric). Relying on the excellent congestion algorithm of the Quic protocol, high bandwidth and low latency can be obtained in a bad network environment. P2P direct connection lets your devices make good use of bandwidth. Your device can be connected in any network environments, even supports NAT1-4 (Cone or Symmetric). Relying on the excellent congestion algorithm of the Quic protocol, high bandwidth and low latency can be obtained in a bad network environment.
### Integration ### 7. Integration
Your applicaiton can call OpenP2P with a few code to make any internal networks communicate with each other. Your applicaiton can call OpenP2P with a few code to make any internal networks communicate with each other.
## Get Started ## Get Started
A common scenario to introduce OpenP2P: remote work. At home connects to office's Linux PC . 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. 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. 1. Make sure your office device(Linux) has opened the access of ssh.
``` ```
netstat -nl | grep 22 netstat -nl | grep 22
@@ -31,21 +43,24 @@ Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamenta
Output sample Output sample
![image](/doc/images/officelisten_linux.png) ![image](/doc/images/officelisten_linux.png)
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 tar xzvf ${PackageName}
openp2p -d -node OFFICEPC1 -user USERNAME1 -password PASSWORD1 ./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 Output sample
![image](/doc/images/officeexecute_linux.png) ![image](/doc/images/officeexecute_linux.png)
3. Download the same package of OpenP2P(TBC) on your home deviceunzip and execute below command line. 3. Download OpenP2P on your home deviceunzip 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 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`
> :warning: **Must change the parameters marked in UPPERCASE to your own**
Output sample Output sample
![image](/doc/images/homeconnect_windows.png) ![image](/doc/images/homeconnect_windows.png)
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. 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 +74,17 @@ Under the outbreak of covid-19 pandemic, surely remote work becomes a fundamenta
![image](/doc/images/sshconnect.png) ![image](/doc/images/sshconnect.png)
## [Usage](/USAGE.md) ## Usage
[Here](/USAGE.md) is a detailed description of how to use and running parameters
## Scenarios ## Scenarios
Especially suitable for large traffic intranet access. Especially suitable for large traffic intranet access.
### Remote work >* Remote work: Windows MSTSC, VNC and other remote desktops, SSH, various ERP systems in the intranet
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 NAS >* Remote access camera
Manage a large number of videos and pictures >* Remote flashing phone
### Remote Access Camera >* Remotely data backup
### Remote Flashing Phone
### Remotely Data Backup
--- ---
## Overview Design ## Overview Design
### Prototype ### Prototype
@@ -81,19 +95,16 @@ Manage a large number of videos and pictures
P2PAPP is the most import concept in this project, one P2PApp is able to map the remote service(mstsc/ssh) to the local listening. The main job of re-development or restful API we provide is to manage P2PApp. P2PAPP is the most import concept in this project, one P2PApp is able to map the remote service(mstsc/ssh) to the local listening. The main job of re-development or restful API we provide is to manage P2PApp.
![image](/doc/images/appdetail.png) ![image](/doc/images/appdetail.png)
## 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.
## Safety ## 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. 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.
### TLS1.3+AES ### 1. TLS1.3+AES
The communication data between the two nodes uses the industry's most secure TLS1.3 channel. The communication content will also use AES encryption, double security, the key is exchanged through the server. Effectively prevent man-in-the-middle attacks. The communication data between the two nodes uses the industry's most secure TLS1.3 channel. The communication content will also use AES encryption, double security, the key is exchanged through the server. Effectively prevent man-in-the-middle attacks.
### Will the shared node capture my data? ### 2. Will the shared node capture my data?
That's right, the relay node is naturally an man-in-middle, so AES encryption is added to ensure the security of the communication content. The relay node cannot obtain the plaintext. That's right, the relay node is naturally an man-in-middle, so AES encryption is added to ensure the security of the communication content. The relay node cannot obtain the plaintext.
### How does the shared relay node verify the authority? ### 3. How does the shared relay node verify the authority?
The server side has a scheduling model, which calculate bandwith, ping value,stability and service duration to provide a well-proportioned service to every share node. It uses TOTP(Time-based One-time Password) with hmac-sha256 algorithem, its theory as same as the cellphone validation code or bank cipher coder. The server side has a scheduling model, which calculate bandwith, ping value,stability and service duration to provide a well-proportioned service to every share node. It uses TOTP(Time-based One-time Password) with hmac-sha256 algorithem, its theory as same as the cellphone validation code or bank cipher coder.
## Build ## Build
@@ -123,7 +134,7 @@ Short-Term:
Long-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. 2. Enterprise-level product can well manage large scale equipment and ACL.
@@ -135,10 +146,6 @@ QQ Group: 16947733
Email: openp2p.cn@gmail.com tenderiron@139.com 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 ## Disclaimer
This project is open source for everyone to learn and use for free. It is forbidden to be used for illegal purposes. Any loss caused by improper use of this project or accident, this project and related personnel will not bear any responsibility. This project is open source for everyone to learn and use for free. It is forbidden to be used for illegal purposes. Any loss caused by improper use of this project or accident, this project and related personnel will not bear any responsibility.
+32 -18
View File
@@ -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进程 >* install: 安装模式推荐】,会安装成系统服务,这样它就能随系统自动启动
>* -node 独一无二的节点名字,唯一标识 >* -d: daemon模式。发现worker进程意外退出就会自动启动新的worker进程
>* -user 独一无二的用户名字,该节点属于这个user >* -node: 独一无二的节点名字,唯一标识
>* -password 密码 >* -user: 独一无二的用户名字,该节点属于这个user
>* -sharebandwidth 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好 >* -password: 密码
>* -loglevel 需要查看更多调试日志,设置0;默认是1 >* -sharebandwidth: 作为共享节点时提供带宽,默认10mbps. 如果是光纤大带宽,设置越大效果越好
>* -noshare 不共享,该节点只在私有的P2P网络使用。不加入共享的P2P网络,这样也意味着无法使用别人的共享节点 >* -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 目标节点名字 >* -peernode: 目标节点名字
>* -dstip 目标服务地址,默认本机127.0.0.1 >* -dstip: 目标服务地址,默认本机127.0.0.1
>* -dstport 目标服务端口,常见的如windows远程桌面3389Linux ssh 22 >* -dstport: 目标服务端口,常见的如windows远程桌面3389Linux ssh 22
>* -protocol 目标服务协议 tcp、udp >* -protocol: 目标服务协议 tcp、udp
>* -peeruser 目标用户,如果是同一个用户下的节点,则无需设置 >* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置
>* -peerpassword 目标密码,如果是同一个用户下的节点,则无需设置 >* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置
>* -f 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json) >* -f: 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json)
## 升级客户端 ## 升级客户端
``` ```
# update local client # update local client
openp2p update ./openp2p update
# update remote client # update remote client
curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password=' curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password='
``` ```
@@ -39,3 +48,8 @@ systemctl stop firewalld.service
systemctl start firewalld.service systemctl start firewalld.service
firewall-cmd --state firewall-cmd --state
``` ```
## 卸载
```
./openp2p uninstall
```
+33 -18
View File
@@ -1,33 +1,43 @@
# Parameters details # 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 >* install: [recommand] will install as system service. So it will autorun when system booting.
>* -node Unique node name, unique identification >* -d: daemon mode run once. When the worker process is found to exit unexpectedly, a new worker process will be automatically started
>* -user Unique user name, the node belongs to this user >* -node: Unique node name, unique identification
>* -password Password >* -user: Unique user name, the node belongs to this user
>* -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 >* -password: Password
>* -loglevel Need to view more debug logs, set 0; the default is 1 >* -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
>* -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 peoples shared nodes >* -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 peoples shared nodes
## Connect ## 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 >* -peernode: Target node name
>* -dstip Target service address, default local 127.0.0.1 >* -dstip: Target service address, default local 127.0.0.1
>* -dstport Target service port, such as windows remote desktop 3389, Linux ssh 22 >* -dstport: Target service port, such as windows remote desktop 3389, Linux ssh 22
>* -protocol Target service protocol tcp, udp >* -protocol: Target service protocol tcp, udp
>* -peeruser The target user, if it is a node under the same user, no need to set >* -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 >* -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) >* -f: Configuration file, if you want to configure multiple P2PApp refer to [config.json](/config.json)
## Client update ## Client update
``` ```
# update local client # update local client
openp2p update ./openp2p update
# update remote client # update remote client
curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password=' curl --insecure 'https://openp2p.cn:27182/api/v1/device/YOUR-NODE-NAME/update?user=&password='
``` ```
@@ -39,3 +49,8 @@ systemctl stop firewalld.service
systemctl start firewalld.service systemctl start firewalld.service
firewall-cmd --state firewall-cmd --state
``` ```
## Uninstall
```
./openp2p uninstall
```
+49
View File
@@ -1,10 +1,16 @@
package main package main
import ( import (
"bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/tls"
"encoding/json"
"fmt" "fmt"
"net" "net"
"net/http"
"os/exec"
"time"
) )
func getmac(ip string) string { 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]) mode.CryptBlocks(out[:dataLen], in[:dataLen])
return pkcs7UnPadding(out, 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()
}
+4
View File
@@ -39,3 +39,7 @@ func TestAESCBC(t *testing.T) {
} }
} }
func TestNetInfo(t *testing.T) {
log.Println(netInfo())
}
+9 -5
View File
@@ -27,6 +27,7 @@ type AppConfig struct {
shareBandwidth int shareBandwidth int
} }
// TODO: add loglevel, maxlogfilesize
type Config struct { type Config struct {
Network NetworkConfig `json:"network"` Network NetworkConfig `json:"network"`
Apps []AppConfig `json:"apps"` Apps []AppConfig `json:"apps"`
@@ -45,10 +46,13 @@ func (c *Config) add(app AppConfig) {
c.Apps = append(c.Apps, app) c.Apps = append(c.Apps, app)
} }
// func (c *Config) save() { func (c *Config) save() {
// data, _ := json.MarshalIndent(c, "", "") data, _ := json.MarshalIndent(c, "", "")
// ioutil.WriteFile("config.json", data, 0644) err := ioutil.WriteFile("config.json", data, 0644)
// } if err != nil {
gLog.Println(LevelERROR, "save config.json error:", err)
}
}
func (c *Config) load() error { func (c *Config) load() error {
data, err := ioutil.ReadFile("config.json") data, err := ioutil.ReadFile("config.json")
@@ -76,7 +80,7 @@ type NetworkConfig struct {
os string os string
publicIP string publicIP string
natType int natType int
shareBandwidth int ShareBandwidth int
// server info // server info
ServerHost string ServerHost string
ServerPort int ServerPort int
+10 -10
View File
@@ -1,8 +1,8 @@
{ {
"network": { "network": {
"Node": "hhd1207-222", "Node": "YOUR_NODE_NAME",
"User": "tenderiron", "User": "YOUR_USER_NAME",
"Password": "13760636579", "Password": "YOUR_PASSWORD",
"ServerHost": "openp2p.cn", "ServerHost": "openp2p.cn",
"ServerPort": 27182, "ServerPort": 27182,
"UDPPort1": 27182, "UDPPort1": 27182,
@@ -11,18 +11,18 @@
"apps": [ "apps": [
{ {
"Protocol": "tcp", "Protocol": "tcp",
"SrcPort": 53389, "SrcPort": 22,
"PeerNode": "dell720-902", "PeerNode": "YOURNODE1",
"DstPort": 3389, "DstPort": 22,
"DstHost": "10.1.6.36", "DstHost": "127.0.0.1",
"PeerUser": "", "PeerUser": "",
"PeerPassword": "" "PeerPassword": ""
}, },
{ {
"Protocol": "tcp", "Protocol": "tcp",
"SrcPort": 22, "SrcPort": 50022,
"PeerNode": "dell720-902", "PeerNode": "YOURNODE2",
"DstPort": 22, "DstPort": 50022,
"DstHost": "127.0.0.1", "DstHost": "127.0.0.1",
"PeerUser": "", "PeerUser": "",
"PeerPassword": "" "PeerPassword": ""
+198 -3
View File
@@ -1,16 +1,60 @@
package main package main
import ( import (
"flag"
"fmt"
"io"
"os" "os"
"path/filepath"
"time" "time"
"github.com/kardianos/service"
) )
type daemon struct { 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() { func (d *daemon) run() {
gLog.Println(LevelINFO, "daemon start") gLog.Println(LevelINFO, "daemon run start")
defer gLog.Println(LevelINFO, "daemon end") 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 var args []string
// rm -d parameter // rm -d parameter
for i := 0; i < len(os.Args); i++ { for i := 0; i < len(os.Args); i++ {
@@ -24,13 +68,164 @@ func (d *daemon) run() {
// start worker // start worker
gLog.Println(LevelINFO, "start worker process") gLog.Println(LevelINFO, "start worker process")
execSpec := &os.ProcAttr{Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}} 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 { if err != nil {
gLog.Printf(LevelERROR, "start worker error:%s", err) gLog.Printf(LevelERROR, "start worker error:%s", err)
return return
} }
d.proc = p
_, _ = p.Wait() _, _ = p.Wait()
if !d.running {
return
}
gLog.Printf(LevelERROR, "worker stop, restart it after 10s") gLog.Printf(LevelERROR, "worker stop, restart it after 10s")
time.Sleep(time.Second * 10) 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.MkdirAll(defaultInstallPath, 0775)
err := os.Chdir(defaultInstallPath)
if err != nil {
gLog.Println(LevelERROR, "cd error:", err)
}
gConf.save()
// 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 {
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

+13
View File
@@ -0,0 +1,13 @@
package main
import (
"errors"
)
// error message
var (
// ErrorS2S string = "s2s is not supported"
// ErrorHandshake string = "handshake error"
ErrorS2S = errors.New("s2s is not supported")
ErrorHandshake = errors.New("handshake error")
)
+1
View File
@@ -4,6 +4,7 @@ go 1.16
require ( require (
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/kardianos/service v1.2.0
github.com/lucas-clemente/quic-go v0.24.0 github.com/lucas-clemente/quic-go v0.24.0
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34
) )
+3 -16
View File
@@ -1,7 +1,6 @@
package main package main
import ( import (
"fmt"
"log" "log"
"os" "os"
"runtime" "runtime"
@@ -55,7 +54,6 @@ type V8log struct {
stoped bool stoped bool
lineEnding string lineEnding string
pid int pid int
lastError string
maxLogSize int64 maxLogSize int64
mode int mode int
} }
@@ -89,7 +87,7 @@ func InitLogger(path string, filePrefix string, level LogLevel, maxLogSize int64
} else { } else {
le = "\n" 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() go pLog.checkFile()
return pLog return pLog
} }
@@ -155,15 +153,11 @@ func (vl *V8log) Printf(level LogLevel, format string, params ...interface{}) {
if level < vl.llevel { if level < vl.llevel {
return return
} }
if level == LevelERROR {
vl.lastError = fmt.Sprintf(format, params...)
}
pidAndLevel := []interface{}{vl.pid, loglevel[level]} pidAndLevel := []interface{}{vl.pid, loglevel[level]}
params = append(pidAndLevel, params...) params = append(pidAndLevel, params...)
if vl.mode == LogFile || vl.mode == LogFileAndConsole { if vl.mode == LogFile || vl.mode == LogFileAndConsole {
vl.loggers[0].Printf("%d %s "+format+vl.lineEnding, params...) vl.loggers[0].Printf("%d %s "+format+vl.lineEnding, params...)
} }
if vl.mode == LogConsole || vl.mode == LogFileAndConsole { if vl.mode == LogConsole || vl.mode == LogFileAndConsole {
log.Printf("%d %s "+format+vl.lineEnding, params...) log.Printf("%d %s "+format+vl.lineEnding, params...)
} }
@@ -179,20 +173,13 @@ func (vl *V8log) Println(level LogLevel, params ...interface{}) {
if level < vl.llevel { if level < vl.llevel {
return return
} }
if level == LevelERROR {
vl.lastError = fmt.Sprint(params...)
}
pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "} pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "}
params = append(pidAndLevel, params...) params = append(pidAndLevel, params...)
params = append(params, vl.lineEnding) params = append(params, vl.lineEnding)
if vl.mode == LogFile || vl.mode == LogFileAndConsole {
vl.loggers[0].Print(params...) vl.loggers[0].Print(params...)
}
if vl.mode == LogConsole || vl.mode == LogFileAndConsole { if vl.mode == LogConsole || vl.mode == LogFileAndConsole {
log.Print(params...) log.Print(params...)
} }
} }
func (vl *V8log) getLastError() string {
vl.mtx.Lock()
defer vl.mtx.Unlock()
return vl.lastError
}
+37 -13
View File
@@ -8,7 +8,7 @@ import (
"time" "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)) conn, err := net.ListenPacket("udp", fmt.Sprintf(":%d", localPort))
if err != nil { if err != nil {
return "", 0, 0, err 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. // 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) _, err = conn.WriteTo(msg, dst)
if err != nil { if err != nil {
return "", 0, 0, err return "", 0, 0, err
@@ -39,14 +39,44 @@ func natTest(serverHost string, serverPort int, localPort int) (publicIP string,
} }
natRsp := NatDetectRsp{} natRsp := NatDetectRsp{}
err = json.Unmarshal(buffer[openP2PHeaderSize:nRead], &natRsp) 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 return natRsp.IP, natRsp.IsPublicIP, natRsp.Port, nil
} }
func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, err error) { func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int, err error) {
// the random local port may be used by other. // the random local port may be used by other.
go echo()
localPort := int(rand.Uint32()%10000 + 50000) 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) gLog.Printf(LevelDEBUG, "local port:%d nat port:%d", localPort, port1)
if err != nil { if err != nil {
return "", 0, err return "", 0, err
@@ -54,7 +84,7 @@ func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int,
if isPublicIP == 1 { if isPublicIP == 1 {
return ip1, NATNone, nil 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) gLog.Printf(LevelDEBUG, "local port:%d nat port:%d", localPort, port2)
if err != nil { if err != nil {
return "", 0, err return "", 0, err
@@ -70,14 +100,8 @@ func getNATType(host string, udp1 int, udp2 int) (publicIP string, NATType int,
return ip1, natType, nil return ip1, natType, nil
} }
const ( func echo(echoPort int) {
UDPPort1 = 27182 conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: echoPort})
UDPPort2 = 27183
EchoPort = 31415
)
func echo() {
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: EchoPort})
if err != nil { if err != nil {
gLog.Println(LevelERROR, "echo server listen error:", err) gLog.Println(LevelERROR, "echo server listen error:", err)
return return
+22 -18
View File
@@ -11,6 +11,7 @@ import (
func main() { func main() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
// TODO: install sub command, deamon process // 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") // 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 { if len(os.Args) > 1 {
@@ -19,12 +20,27 @@ func main() {
fmt.Println(OpenP2PVersion) fmt.Println(OpenP2PVersion)
return return
case "update": 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() 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 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") user := flag.String("user", "", "user name. 8-31 characters")
node := flag.String("node", "", "node name. 8-31 characters") node := flag.String("node", "", "node name. 8-31 characters")
password := flag.String("password", "", "user password. 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)") peerUser := flag.String("peeruser", "", "peer node user (default peeruser=user)")
peerPassword := flag.String("peerpassword", "", "peer node password (default peerpassword=password)") peerPassword := flag.String("peerpassword", "", "peer node password (default peerpassword=password)")
dstIP := flag.String("dstip", "127.0.0.1", "destination ip ") 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 ") dstPort := flag.Int("dstport", 0, "destination port ")
srcPort := flag.Int("srcport", 0, "source port ") srcPort := flag.Int("srcport", 0, "source port ")
protocol := flag.String("protocol", "tcp", "tcp or udp") protocol := flag.String("protocol", "tcp", "tcp or udp")
@@ -44,7 +58,8 @@ func main() {
byDaemon := flag.Bool("bydaemon", false, "start by daemon") byDaemon := flag.Bool("bydaemon", false, "start by daemon")
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error") logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
flag.Parse() 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) gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
if *daemonMode { if *daemonMode {
d := daemon{} d := daemon{}
@@ -53,18 +68,7 @@ func main() {
} }
if !*configFile { if !*configFile {
// validate cmd params // validate cmd params
if *node == "" { checkParams(*node, *user, *password)
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
}
if *peerNode != "" { if *peerNode != "" {
if *dstPort == 0 { if *dstPort == 0 {
gLog.Println(LevelERROR, "dstPort not set") gLog.Println(LevelERROR, "dstPort not set")
@@ -103,7 +107,7 @@ func main() {
UDPPort1: 27182, UDPPort1: 27182,
UDPPort2: 27183, UDPPort2: 27183,
ipv6: "240e:3b7:621:def0:fda4:dd7f:36a1:2803", // TODO: detect real ipv6 ipv6: "240e:3b7:621:def0:fda4:dd7f:36a1:2803", // TODO: detect real ipv6
shareBandwidth: *shareBandwidth, ShareBandwidth: *shareBandwidth,
} }
} }
// gConf.save() // not change config file // gConf.save() // not change config file
+5
View File
@@ -24,6 +24,9 @@ type p2pApp struct {
} }
func (app *p2pApp) isActive() bool { func (app *p2pApp) isActive() bool {
if app.tunnel == nil {
return false
}
if app.rtid == 0 { // direct mode app heartbeat equals to tunnel heartbeat if app.rtid == 0 { // direct mode app heartbeat equals to tunnel heartbeat
return app.tunnel.isActive() return app.tunnel.isActive()
} }
@@ -119,7 +122,9 @@ func (app *p2pApp) close() {
if app.listener != nil { if app.listener != nil {
app.listener.Close() app.listener.Close()
} }
if app.tunnel != nil {
app.tunnel.closeOverlayConns(app.id) app.tunnel.closeOverlayConns(app.id)
}
app.wg.Wait() app.wg.Wait()
} }
+26 -19
View File
@@ -7,8 +7,8 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"math"
"math/rand" "math/rand"
"net"
"net/url" "net/url"
"os" "os"
"strings" "strings"
@@ -30,7 +30,8 @@ type P2PNetwork struct {
restartCh chan bool restartCh chan bool
wg sync.WaitGroup wg sync.WaitGroup
writeMtx sync.Mutex writeMtx sync.Mutex
serverTs uint64 serverTs int64
localTs int64
// msgMap sync.Map // msgMap sync.Map
msgMap map[uint64]chan []byte //key: nodeID msgMap map[uint64]chan []byte //key: nodeID
msgMapMtx sync.Mutex msgMapMtx sync.Mutex
@@ -48,7 +49,7 @@ func P2PNetworkInstance(config *NetworkConfig) *P2PNetwork {
online: false, online: false,
running: true, running: true,
msgMap: make(map[uint64]chan []byte), msgMap: make(map[uint64]chan []byte),
limiter: newBandwidthLimiter(config.shareBandwidth), limiter: newBandwidthLimiter(config.ShareBandwidth),
} }
instance.msgMap[0] = make(chan []byte) // for gateway instance.msgMap[0] = make(chan []byte) // for gateway
if config != nil { if config != nil {
@@ -105,10 +106,6 @@ func (pn *P2PNetwork) autoReconnectApp() {
thisRound := make([]AppConfig, 0) thisRound := make([]AppConfig, 0)
for i := 0; i < len(retryApps); i++ { for i := 0; i < len(retryApps); i++ {
// reset retryNum when running 15min continuously // 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()) { if retryApps[i].retryTime.Add(time.Minute * 15).Before(time.Now()) {
retryApps[i].retryNum = 0 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) { func (pn *P2PNetwork) addRelayTunnel(config AppConfig, appid uint64, appkey uint64) (*P2PTunnel, uint64, error) {
gLog.Printf(LevelINFO, "addRelayTunnel to %s start", config.PeerNode) gLog.Printf(LevelINFO, "addRelayTunnel to %s start", config.PeerNode)
defer gLog.Printf(LevelINFO, "addRelayTunnel to %s end", 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) head, body := pn.read("", MsgRelay, MsgRelayNodeRsp, time.Second*10)
if head == nil { if head == nil {
return nil, 0, errors.New("read MsgRelayNodeRsp error") return nil, 0, errors.New("read MsgRelayNodeRsp error")
@@ -253,14 +250,11 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
PeerUser: config.PeerUser, PeerUser: config.PeerUser,
PeerNatType: peerNatType, PeerNatType: peerNatType,
PeerIP: peerIP, PeerIP: peerIP,
ShareBandwidth: pn.config.shareBandwidth, ShareBandwidth: pn.config.ShareBandwidth,
RelayNode: relayNode, RelayNode: relayNode,
Version: OpenP2PVersion, Version: OpenP2PVersion,
} }
pn.write(MsgReport, MsgReportConnect, &req) pn.write(MsgReport, MsgReportConnect, &req)
if err != nil {
return err
}
app := p2pApp{ app := p2pApp{
id: appID, id: appID,
@@ -270,7 +264,9 @@ func (pn *P2PNetwork) AddApp(config AppConfig) error {
rtid: rtid, rtid: rtid,
hbTime: time.Now()} hbTime: time.Now()}
pn.apps.Store(appID, &app) pn.apps.Store(appID, &app)
if err == nil {
go app.listen() go app.listen()
}
return err return err
} }
@@ -377,7 +373,7 @@ func (pn *P2PNetwork) init() error {
// detect nat type // detect nat type
pn.config.publicIP, pn.config.natType, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2) pn.config.publicIP, pn.config.natType, err = getNATType(pn.config.ServerHost, pn.config.UDPPort1, pn.config.UDPPort2)
// TODO rm test s2s // TODO rm test s2s
if pn.config.Node == "hhd1207-222S2S" { if strings.Contains(pn.config.Node, "openp2pS2STest") {
pn.config.natType = NATSymmetric pn.config.natType = NATSymmetric
} }
if err != nil { if err != nil {
@@ -396,7 +392,6 @@ func (pn *P2PNetwork) init() error {
q.Add("password", pn.config.Password) q.Add("password", pn.config.Password)
q.Add("version", OpenP2PVersion) q.Add("version", OpenP2PVersion)
q.Add("nattype", fmt.Sprintf("%d", pn.config.natType)) q.Add("nattype", fmt.Sprintf("%d", pn.config.natType))
q.Add("timestamp", fmt.Sprintf("%d", time.Now().Unix()))
noShareStr := "false" noShareStr := "false"
if pn.config.NoShare { if pn.config.NoShare {
@@ -422,13 +417,22 @@ func (pn *P2PNetwork) init() error {
pn.config.mac = getmac(pn.config.localIP) pn.config.mac = getmac(pn.config.localIP)
pn.config.os = getOsName() pn.config.os = getOsName()
req := ReportBasic{ req := ReportBasic{
Mac: pn.config.mac, Mac: pn.config.mac,
LanIP: pn.config.localIP, LanIP: pn.config.localIP,
OS: pn.config.os, OS: pn.config.os,
IPv6: pn.config.ipv6,
Version: OpenP2PVersion, 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) pn.write(MsgReport, MsgReportBasic, &req)
gLog.Println(LevelINFO, "P2PNetwork init ok") gLog.Println(LevelINFO, "P2PNetwork init ok")
break 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) gLog.Printf(LevelERROR, "login error:%d, detail:%s", rsp.Error, rsp.Detail)
pn.running = false pn.running = false
} else { } else {
gLog.Printf(LevelINFO, "login ok. Server ts=%d, local ts=%d", rsp.Ts, time.Now().Unix())
pn.serverTs = rsp.Ts 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: case MsgHeartbeat:
gLog.Printf(LevelDEBUG, "P2PNetwork heartbeat ok") 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.Printf(LevelINFO, "%s is connecting...", req.From)
gLog.Println(LevelDEBUG, "push connect response to ", req.From) gLog.Println(LevelDEBUG, "push connect response to ", req.From)
// verify token or name&password // 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") gLog.Printf(LevelINFO, "Access Granted\n")
config := AppConfig{} config := AppConfig{}
config.peerNatType = req.NatType config.peerNatType = req.NatType
@@ -614,8 +621,8 @@ func (pn *P2PNetwork) handlePush(subType uint16, msg []byte) error {
config.PeerNode = req.From config.PeerNode = req.From
// share relay node will limit bandwidth // share relay node will limit bandwidth
if req.User != pn.config.User || req.Password != pn.config.Password { if req.User != pn.config.User || req.Password != pn.config.Password {
gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.shareBandwidth) gLog.Printf(LevelINFO, "set share bandwidth %d mbps", pn.config.ShareBandwidth)
config.shareBandwidth = pn.config.shareBandwidth config.shareBandwidth = pn.config.ShareBandwidth
} }
// go pn.AddTunnel(config, req.ID) // go pn.AddTunnel(config, req.ID)
go pn.addDirectTunnel(config, req.ID) go pn.addDirectTunnel(config, req.ID)
+1 -1
View File
@@ -39,7 +39,7 @@ func (t *P2PTunnel) init() {
localPort := int(rand.Uint32()%10000 + 50000) localPort := int(rand.Uint32()%10000 + 50000)
if t.pn.config.natType == NATCone { if t.pn.config.natType == NATCone {
// prepare one random cone hole // 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.coneLocalPort = localPort
t.coneNatPort = port1 t.coneNatPort = port1
t.la = &net.UDPAddr{IP: net.ParseIP(t.pn.config.localIP), Port: t.coneLocalPort} t.la = &net.UDPAddr{IP: net.ParseIP(t.pn.config.localIP), Port: t.coneLocalPort}
+29 -12
View File
@@ -4,12 +4,13 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"errors"
"hash/crc64" "hash/crc64"
"math/big"
"net"
"time" "time"
) )
const OpenP2PVersion = "0.95.5" const OpenP2PVersion = "0.97.1"
const ProducnName string = "openp2p" const ProducnName string = "openp2p"
type openP2PHeader struct { type openP2PHeader struct {
@@ -125,18 +126,10 @@ const (
AESKeySize = 16 AESKeySize = 16
MaxRetry = 10 MaxRetry = 10
RetryInterval = time.Second * 30 RetryInterval = time.Second * 30
PublicIPEchoTimeout = time.Second * 5 PublicIPEchoTimeout = time.Second * 3
NatTestTimeout = time.Second * 10 NatTestTimeout = time.Second * 10
) )
// error message
var (
// ErrorS2S string = "s2s is not supported"
// ErrorHandshake string = "handshake error"
ErrorS2S = errors.New("s2s is not supported")
ErrorHandshake = errors.New("handshake error")
)
// NATNone has public ip // NATNone has public ip
const ( const (
NATNone = 0 NATNone = 0
@@ -196,7 +189,7 @@ type PushRsp struct {
type LoginRsp struct { type LoginRsp struct {
Error int `json:"error,omitempty"` Error int `json:"error,omitempty"`
Detail string `json:"detail,omitempty"` Detail string `json:"detail,omitempty"`
Ts uint64 `json:"ts,omitempty"` Ts int64 `json:"ts,omitempty"`
} }
type NatDetectReq struct { type NatDetectReq struct {
@@ -231,6 +224,10 @@ type TunnelMsg struct {
ID uint64 `json:"id,omitempty"` ID uint64 `json:"id,omitempty"`
} }
type RelayNodeReq struct {
PeerNode string `json:"peerNode,omitempty"`
}
type RelayNodeRsp struct { type RelayNodeRsp struct {
RelayName string `json:"relayName,omitempty"` RelayName string `json:"relayName,omitempty"`
RelayToken uint64 `json:"relayToken,omitempty"` RelayToken uint64 `json:"relayToken,omitempty"`
@@ -255,6 +252,7 @@ type ReportBasic struct {
LanIP string `json:"lanIP,omitempty"` LanIP string `json:"lanIP,omitempty"`
IPv6 string `json:"IPv6,omitempty"` IPv6 string `json:"IPv6,omitempty"`
Version string `json:"version,omitempty"` Version string `json:"version,omitempty"`
NetInfo NetInfo `json:"netInfo,omitempty"`
} }
type ReportConnect struct { type ReportConnect struct {
@@ -278,3 +276,22 @@ type UpdateInfo struct {
ErrorDetail string `json:"errorDetail,omitempty"` ErrorDetail string `json:"errorDetail,omitempty"`
Url string `json:"url,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"`
}
+5
View File
@@ -8,6 +8,11 @@ import (
"syscall" "syscall"
) )
const (
defaultInstallPath = "/usr/local/openp2p"
defaultBinName = "openp2p"
)
func getOsName() (osName string) { func getOsName() (osName string) {
output := execOutput("sw_vers", "-productVersion") output := execOutput("sw_vers", "-productVersion")
osName = "Mac OS X " + strings.TrimSpace(output) osName = "Mac OS X " + strings.TrimSpace(output)
+5
View File
@@ -12,6 +12,11 @@ import (
"syscall" "syscall"
) )
const (
defaultInstallPath = "/usr/local/openp2p"
defaultBinName = "openp2p"
)
func getOsName() (osName string) { func getOsName() (osName string) {
var sysnamePath string var sysnamePath string
sysnamePath = "/etc/redhat-release" sysnamePath = "/etc/redhat-release"
+5
View File
@@ -13,6 +13,11 @@ import (
"golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/registry"
) )
const (
defaultInstallPath = "C:\\Program Files\\OpenP2P"
defaultBinName = "openp2p.exe"
)
func getOsName() (osName string) { func getOsName() (osName string) {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE|registry.WOW64_64KEY) k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE|registry.WOW64_64KEY)
if err != nil { if err != nil {