mirror of https://github.com/ehang-io/nps
commit
f97a9176e7
|
@ -0,0 +1,57 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- "1.13"
|
||||||
|
- master
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
script:
|
||||||
|
- go test -v ./cmd/nps/
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
before_deploy:
|
||||||
|
- chmod +x ./build.sh && ./build.sh
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: releases
|
||||||
|
api_key:
|
||||||
|
secure: ${TOKEN}
|
||||||
|
skip_cleanup: true
|
||||||
|
file:
|
||||||
|
- freebsd_386_client.tar.gz
|
||||||
|
- freebsd_386_server.tar.gz
|
||||||
|
- freebsd_amd64_client.tar.gz
|
||||||
|
- freebsd_amd64_server.tar.gz
|
||||||
|
- freebsd_arm_client.tar.gz
|
||||||
|
- freebsd_arm_server.tar.gz
|
||||||
|
- linux_386_client.tar.gz
|
||||||
|
- linux_386_server.tar.gz
|
||||||
|
- linux_amd64_client.tar.gz
|
||||||
|
- linux_amd64_server.tar.gz
|
||||||
|
- linux_arm64_client.tar.gz
|
||||||
|
- linux_arm64_server.tar.gz
|
||||||
|
- linux_arm_v5_client.tar.gz
|
||||||
|
- linux_arm_v6_client.tar.gz
|
||||||
|
- linux_arm_v7_client.tar.gz
|
||||||
|
- linux_arm_v5_server.tar.gz
|
||||||
|
- linux_arm_v6_server.tar.gz
|
||||||
|
- linux_arm_v7_server.tar.gz
|
||||||
|
- linux_mips64le_client.tar.gz
|
||||||
|
- linux_mips64le_server.tar.gz
|
||||||
|
- linux_mips64_client.tar.gz
|
||||||
|
- linux_mips64_server.tar.gz
|
||||||
|
- linux_mipsle_client.tar.gz
|
||||||
|
- linux_mipsle_server.tar.gz
|
||||||
|
- linux_mips_client.tar.gz
|
||||||
|
- linux_mips_server.tar.gz
|
||||||
|
- macos_client.tar.gz
|
||||||
|
- macos_server.tar.gz
|
||||||
|
- win_386_client.tar.gz
|
||||||
|
- win_386_server.tar.gz
|
||||||
|
- win_amd64_client.tar.gz
|
||||||
|
- win_amd64_server.tar.gz
|
||||||
|
- npc_syno.spk
|
||||||
|
- npc_sdk.tar.gz
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
all_branches: true
|
26
README.md
26
README.md
|
@ -2,6 +2,7 @@
|
||||||
# nps
|
# nps
|
||||||
 
|
 
|
||||||
[](https://gitter.im/cnlh-nps/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](https://gitter.im/cnlh-nps/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
|
[](https://travis-ci.org/cnlh/nps)
|
||||||
|
|
||||||
nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务器。目前支持**tcp、udp流量转发**,可支持任何**tcp、udp**上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还**支持内网http代理、内网socks5代理**、**p2p等**,并带有功能强大的web管理端。
|
nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务器。目前支持**tcp、udp流量转发**,可支持任何**tcp、udp**上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还**支持内网http代理、内网socks5代理**、**p2p等**,并带有功能强大的web管理端。
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务
|
||||||
* [配置文件说明](#服务端配置文件)
|
* [配置文件说明](#服务端配置文件)
|
||||||
* [使用https](#使用https)
|
* [使用https](#使用https)
|
||||||
* [与nginx配合](#与nginx配合)
|
* [与nginx配合](#与nginx配合)
|
||||||
|
* [web使用Caddy代理](#web使用Caddy代理)
|
||||||
* [关闭http|https代理](#关闭代理)
|
* [关闭http|https代理](#关闭代理)
|
||||||
* [将nps安装到系统](#将nps安装到系统)
|
* [将nps安装到系统](#将nps安装到系统)
|
||||||
* [流量数据持久化](#流量数据持久化)
|
* [流量数据持久化](#流量数据持久化)
|
||||||
|
@ -317,6 +319,7 @@ nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务
|
||||||
web_port | web管理端口
|
web_port | web管理端口
|
||||||
web_password | web界面管理密码
|
web_password | web界面管理密码
|
||||||
web_username | web界面管理账号
|
web_username | web界面管理账号
|
||||||
|
web_base_url | web管理主路径,用于将web管理置于代理子路径后面
|
||||||
bridge_port | 服务端客户端通信端口
|
bridge_port | 服务端客户端通信端口
|
||||||
https_proxy_port | 域名代理https代理监听端口
|
https_proxy_port | 域名代理https代理监听端口
|
||||||
http_proxy_port | 域名代理http代理监听端口
|
http_proxy_port | 域名代理http代理监听端口
|
||||||
|
@ -375,6 +378,29 @@ server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### web使用Caddy代理
|
||||||
|
|
||||||
|
如果将web配置到Caddy代理,实现子路径访问nps,可以这样配置.
|
||||||
|
|
||||||
|
假设我们想通过 `http://caddy_ip:caddy_port/nps` 来访问后台, Caddyfile 这样配置:
|
||||||
|
|
||||||
|
```Caddyfile
|
||||||
|
caddy_ip:caddy_port/nps {
|
||||||
|
#server_ip 为 nps 服务器IP
|
||||||
|
#web_port 为 nps 后台端口
|
||||||
|
proxy / http://server_ip:web_port/nps {
|
||||||
|
transparent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
nps.conf 修改 `web_base_url` 为 `/nps` 即可
|
||||||
|
```
|
||||||
|
web_base_url=/nps
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### 关闭代理
|
### 关闭代理
|
||||||
|
|
||||||
如需关闭http代理可在配置文件中将http_proxy_port设置为空,如需关闭https代理可在配置文件中将https_proxy_port设置为空。
|
如需关闭http代理可在配置文件中将http_proxy_port设置为空,如需关闭https代理可在配置文件中将https_proxy_port设置为空。
|
||||||
|
|
|
@ -27,14 +27,16 @@ type Client struct {
|
||||||
tunnel *mux.Mux
|
tunnel *mux.Mux
|
||||||
signal *conn.Conn
|
signal *conn.Conn
|
||||||
file *mux.Mux
|
file *mux.Mux
|
||||||
|
Version string
|
||||||
retryTime int // it will be add 1 when ping not ok until to 3 will close the client
|
retryTime int // it will be add 1 when ping not ok until to 3 will close the client
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(t, f *mux.Mux, s *conn.Conn) *Client {
|
func NewClient(t, f *mux.Mux, s *conn.Conn, vs string) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
signal: s,
|
signal: s,
|
||||||
tunnel: t,
|
tunnel: t,
|
||||||
file: f,
|
file: f,
|
||||||
|
Version: vs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,16 +168,23 @@ func (s *Bridge) cliProcess(c *conn.Conn) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//version check
|
//version check
|
||||||
if b, err := c.GetShortContent(32); err != nil || string(b) != crypt.Md5(version.GetVersion()) {
|
if b, err := c.GetShortLenContent(); err != nil || string(b) != version.GetVersion() {
|
||||||
logs.Info("The client %s version does not match", c.Conn.RemoteAddr())
|
logs.Info("The client %s version does not match", c.Conn.RemoteAddr())
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
//version get
|
||||||
|
var vs []byte
|
||||||
|
var err error
|
||||||
|
if vs, err = c.GetShortLenContent(); err != nil {
|
||||||
|
logs.Info("get client %s version error", err.Error())
|
||||||
|
c.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
//write server version to client
|
//write server version to client
|
||||||
c.Write([]byte(crypt.Md5(version.GetVersion())))
|
c.Write([]byte(crypt.Md5(version.GetVersion())))
|
||||||
c.SetReadDeadlineBySecond(5)
|
c.SetReadDeadlineBySecond(5)
|
||||||
var buf []byte
|
var buf []byte
|
||||||
var err error
|
|
||||||
//get vKey from client
|
//get vKey from client
|
||||||
if buf, err = c.GetShortContent(32); err != nil {
|
if buf, err = c.GetShortContent(32); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
|
@ -191,7 +200,7 @@ func (s *Bridge) cliProcess(c *conn.Conn) {
|
||||||
s.verifySuccess(c)
|
s.verifySuccess(c)
|
||||||
}
|
}
|
||||||
if flag, err := c.ReadFlag(); err == nil {
|
if flag, err := c.ReadFlag(); err == nil {
|
||||||
s.typeDeal(flag, c, id)
|
s.typeDeal(flag, c, id, string(vs))
|
||||||
} else {
|
} else {
|
||||||
logs.Warn(err, flag)
|
logs.Warn(err, flag)
|
||||||
}
|
}
|
||||||
|
@ -214,7 +223,7 @@ func (s *Bridge) DelClient(id int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//use different
|
//use different
|
||||||
func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
|
func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int, vs string) {
|
||||||
isPub := file.GetDb().IsPubClient(id)
|
isPub := file.GetDb().IsPubClient(id)
|
||||||
switch typeVal {
|
switch typeVal {
|
||||||
case common.WORK_MAIN:
|
case common.WORK_MAIN:
|
||||||
|
@ -223,17 +232,18 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//the vKey connect by another ,close the client of before
|
//the vKey connect by another ,close the client of before
|
||||||
if v, ok := s.Client.LoadOrStore(id, NewClient(nil, nil, c)); ok {
|
if v, ok := s.Client.LoadOrStore(id, NewClient(nil, nil, c, vs)); ok {
|
||||||
if v.(*Client).signal != nil {
|
if v.(*Client).signal != nil {
|
||||||
v.(*Client).signal.WriteClose()
|
v.(*Client).signal.WriteClose()
|
||||||
}
|
}
|
||||||
v.(*Client).signal = c
|
v.(*Client).signal = c
|
||||||
|
v.(*Client).Version = vs
|
||||||
}
|
}
|
||||||
go s.GetHealthFromClient(id, c)
|
go s.GetHealthFromClient(id, c)
|
||||||
logs.Info("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr())
|
logs.Info("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr())
|
||||||
case common.WORK_CHAN:
|
case common.WORK_CHAN:
|
||||||
muxConn := mux.NewMux(c.Conn, s.tunnelType)
|
muxConn := mux.NewMux(c.Conn, s.tunnelType)
|
||||||
if v, ok := s.Client.LoadOrStore(id, NewClient(muxConn, nil, nil)); ok {
|
if v, ok := s.Client.LoadOrStore(id, NewClient(muxConn, nil, nil, vs)); ok {
|
||||||
v.(*Client).tunnel = muxConn
|
v.(*Client).tunnel = muxConn
|
||||||
}
|
}
|
||||||
case common.WORK_CONFIG:
|
case common.WORK_CONFIG:
|
||||||
|
@ -254,7 +264,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
|
||||||
}
|
}
|
||||||
case common.WORK_FILE:
|
case common.WORK_FILE:
|
||||||
muxConn := mux.NewMux(c.Conn, s.tunnelType)
|
muxConn := mux.NewMux(c.Conn, s.tunnelType)
|
||||||
if v, ok := s.Client.LoadOrStore(id, NewClient(nil, muxConn, nil)); ok {
|
if v, ok := s.Client.LoadOrStore(id, NewClient(nil, muxConn, nil, vs)); ok {
|
||||||
v.(*Client).file = muxConn
|
v.(*Client).file = muxConn
|
||||||
}
|
}
|
||||||
case common.WORK_P2P:
|
case common.WORK_P2P:
|
||||||
|
@ -419,7 +429,7 @@ loop:
|
||||||
}
|
}
|
||||||
c.WriteAddOk()
|
c.WriteAddOk()
|
||||||
c.Write([]byte(client.VerifyKey))
|
c.Write([]byte(client.VerifyKey))
|
||||||
s.Client.Store(client.Id, NewClient(nil, nil, nil))
|
s.Client.Store(client.Id, NewClient(nil, nil, nil, ""))
|
||||||
}
|
}
|
||||||
case common.NEW_HOST:
|
case common.NEW_HOST:
|
||||||
h, err := c.GetHostInfo()
|
h, err := c.GetHostInfo()
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
#!/bin/bash
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_amd64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_386_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf freebsd_386_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf freebsd_amd64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=arm go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf freebsd_arm_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_arm_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_arm64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_mips64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_mips64le_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_mipsle_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf linux_mips_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf win_386_client.tar.gz npc.exe conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf win_amd64_client.tar.gz npc.exe conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
upx npc
|
||||||
|
tar -czvf macos_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_amd64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_386_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_arm_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_arm64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=arm go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf freebsd_arm_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf freebsd_386_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf freebsd_amd64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_mips_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_mips64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_mips64le_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf linux_mipsle_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps
|
||||||
|
tar -czvf macos_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps.exe
|
||||||
|
tar -czvf win_amd64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps.exe
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
upx nps.exe
|
||||||
|
tar -czvf win_386_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps.exe
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
#/bash/sh
|
||||||
|
|
||||||
|
sudo apt-get install gcc-mingw-w64-i686
|
||||||
|
env GOOS=windows GOARCH=386 CGO_ENABLED=1 CC=i686-w64-mingw32-gcc go build -ldflags "-s -w -extldflags -static -extldflags -static" -buildmode=c-shared -o npc_sdk.dll cmd/npc/sdk.go
|
||||||
|
tar -czvf npc_sdk.tar.gz npc_sdk.dll npc_sdk.h
|
||||||
|
|
||||||
|
wget https://github.com/upx/upx/releases/download/v3.95/upx-3.95-amd64_linux.tar.xz
|
||||||
|
tar -xvf upx-3.95-amd64_linux.tar.xz
|
||||||
|
cp upx-3.95-amd64_linux/upx ./
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_amd64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_386_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf freebsd_386_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf freebsd_amd64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=arm go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf freebsd_arm_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm_v7_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm_v6_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm_v5_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_mips64_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_mips64le_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_mipsle_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf linux_mips_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf win_386_client.tar.gz npc.exe conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf win_amd64_client.tar.gz npc.exe conf/npc.conf
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/npc/npc.go
|
||||||
|
|
||||||
|
tar -czvf macos_client.tar.gz npc conf/npc.conf
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_amd64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_386_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm_v5_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm_v6_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm_v7_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_arm64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=arm go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf freebsd_arm_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf freebsd_386_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf freebsd_amd64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_mips_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_mips64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_mips64le_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf linux_mipsle_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf macos_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf win_amd64_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps.exe
|
||||||
|
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags "-s -w -extldflags -static -extldflags -static" ./cmd/nps/nps.go
|
||||||
|
|
||||||
|
tar -czvf win_386_server.tar.gz conf/nps.conf conf/tasks.json conf/clients.json conf/hosts.json conf/server.key conf/server.pem web/views web/static nps.exe
|
||||||
|
|
||||||
|
export VERSION=0.25.0
|
||||||
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||||
|
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
||||||
|
docker --version
|
||||||
|
git clone https://github.com/cnlh/spksrc.git ~/spksrc
|
||||||
|
mkdir ~/spksrc/nps && cp -rf ./* ~/spksrc/nps/
|
||||||
|
docker run -itd --name spksrc --env VERSION=$VERSION -v ~/spksrc:/spksrc synocommunity/spksrc /bin/bash
|
||||||
|
docker exec -it spksrc /bin/bash -c 'cd /spksrc && make setup && cd /spksrc/spk/npc && make'
|
||||||
|
cp ~/spksrc/packages/npc_noarch-all_$VERSION-1.spk ./npc_syno.spk
|
||||||
|
|
||||||
|
|
||||||
|
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||||
|
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
|
docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
|
||||||
|
docker buildx create --use --name mybuilder
|
||||||
|
docker buildx build --tag ffdfgdfg/nps:$VERSION --output type=image,push=true --file Dockerfile.nps --platform=linux/amd64,linux/arm64,linux/386,linux/arm .
|
||||||
|
docker buildx build --tag ffdfgdfg/npc:$VERSION --output type=image,push=true --file Dockerfile.npc --platform=linux/amd64,linux/arm64,linux/386,linux/arm .
|
|
@ -2,18 +2,20 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/logs"
|
"github.com/astaxie/beego/logs"
|
||||||
|
"github.com/xtaci/kcp-go"
|
||||||
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/config"
|
"github.com/cnlh/nps/lib/config"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/crypt"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/mux"
|
"github.com/cnlh/nps/lib/mux"
|
||||||
"github.com/xtaci/kcp-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TRPClient struct {
|
type TRPClient struct {
|
||||||
|
@ -156,7 +158,7 @@ func (s *TRPClient) newChan() {
|
||||||
|
|
||||||
func (s *TRPClient) handleChan(src net.Conn) {
|
func (s *TRPClient) handleChan(src net.Conn) {
|
||||||
lk, err := conn.NewConn(src).GetLinkInfo()
|
lk, err := conn.NewConn(src).GetLinkInfo()
|
||||||
if err != nil {
|
if err != nil || lk == nil {
|
||||||
src.Close()
|
src.Close()
|
||||||
logs.Error("get connection info from server error ", err)
|
logs.Error("get connection info from server error ", err)
|
||||||
return
|
return
|
||||||
|
@ -165,7 +167,7 @@ func (s *TRPClient) handleChan(src net.Conn) {
|
||||||
lk.Host = common.FormatAddress(lk.Host)
|
lk.Host = common.FormatAddress(lk.Host)
|
||||||
//if Conn type is http, read the request and log
|
//if Conn type is http, read the request and log
|
||||||
if lk.ConnType == "http" {
|
if lk.ConnType == "http" {
|
||||||
if targetConn, err := net.Dial(common.CONN_TCP, lk.Host); err != nil {
|
if targetConn, err := net.DialTimeout(common.CONN_TCP, lk.Host, lk.Option.Timeout); err != nil {
|
||||||
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
||||||
src.Close()
|
src.Close()
|
||||||
} else {
|
} else {
|
||||||
|
@ -188,8 +190,12 @@ func (s *TRPClient) handleChan(src net.Conn) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if lk.ConnType == "udp5" {
|
||||||
|
logs.Trace("new %s connection with the goal of %s, remote address:%s", lk.ConnType, lk.Host, lk.RemoteAddr)
|
||||||
|
s.handleUdp(src)
|
||||||
|
}
|
||||||
//connect to target if conn type is tcp or udp
|
//connect to target if conn type is tcp or udp
|
||||||
if targetConn, err := net.Dial(lk.ConnType, lk.Host); err != nil {
|
if targetConn, err := net.DialTimeout(lk.ConnType, lk.Host, lk.Option.Timeout); err != nil {
|
||||||
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
logs.Warn("connect to %s error %s", lk.Host, err.Error())
|
||||||
src.Close()
|
src.Close()
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,6 +204,65 @@ func (s *TRPClient) handleChan(src net.Conn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TRPClient) handleUdp(serverConn net.Conn) {
|
||||||
|
// bind a local udp port
|
||||||
|
local, err := net.ListenUDP("udp", nil)
|
||||||
|
defer local.Close()
|
||||||
|
defer serverConn.Close()
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("bind local udp port error ", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer serverConn.Close()
|
||||||
|
b := common.BufPoolUdp.Get().([]byte)
|
||||||
|
defer common.BufPoolUdp.Put(b)
|
||||||
|
for {
|
||||||
|
n, raddr, err := local.ReadFrom(b)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("read data from remote server error", err.Error())
|
||||||
|
}
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
dgram := common.NewUDPDatagram(common.NewUDPHeader(0, 0, common.ToSocksAddr(raddr)), b[:n])
|
||||||
|
dgram.Write(&buf)
|
||||||
|
b, err := conn.GetLenBytes(buf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
logs.Warn("get len bytes error", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := serverConn.Write(b); err != nil {
|
||||||
|
logs.Error("write data to remote error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
b := common.BufPoolUdp.Get().([]byte)
|
||||||
|
defer common.BufPoolUdp.Put(b)
|
||||||
|
for {
|
||||||
|
n, err := serverConn.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("read udp data from server error ", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
udpData, err := common.ReadUDPDatagram(bytes.NewReader(b[:n]))
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("unpack data error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
raddr, err := net.ResolveUDPAddr("udp", udpData.Header.Addr.String())
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("build remote addr err", err.Error())
|
||||||
|
continue // drop silently
|
||||||
|
}
|
||||||
|
_, err = local.WriteTo(udpData.Data, raddr)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("write data to remote ", raddr.String(), "error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Whether the monitor channel is closed
|
// Whether the monitor channel is closed
|
||||||
func (s *TRPClient) ping() {
|
func (s *TRPClient) ping() {
|
||||||
s.ticker = time.NewTicker(time.Second * 5)
|
s.ticker = time.NewTicker(time.Second * 5)
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
|
||||||
conn2 "github.com/cnlh/nps/lib/conn"
|
|
||||||
"github.com/cnlh/nps/lib/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestConfig(t *testing.T) {
|
|
||||||
conn, err := net.Dial("tcp", "127.0.0.1:8284")
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
c := conn2.NewConn(conn)
|
|
||||||
c.SetAlive("tcp")
|
|
||||||
if _, err := c.Write([]byte(common.Getverifyval("123"))); err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
c.WriteConfig()
|
|
||||||
config := &file.Config{
|
|
||||||
U: "1",
|
|
||||||
P: "2",
|
|
||||||
Compress: "snappy",
|
|
||||||
Crypt: true,
|
|
||||||
CompressEncode: 0,
|
|
||||||
CompressDecode: 0,
|
|
||||||
}
|
|
||||||
host := &file.Host{
|
|
||||||
Host: "a.o.com",
|
|
||||||
Target: "127.0.0.1:8080",
|
|
||||||
HeaderChange: "",
|
|
||||||
HostChange: "",
|
|
||||||
Flow: nil,
|
|
||||||
Client: nil,
|
|
||||||
Remark: "111",
|
|
||||||
NowIndex: 0,
|
|
||||||
TargetArr: nil,
|
|
||||||
NoStore: false,
|
|
||||||
RWMutex: sync.RWMutex{},
|
|
||||||
}
|
|
||||||
tunnel := &file.Tunnel{
|
|
||||||
Port: 9001,
|
|
||||||
Mode: "tcp",
|
|
||||||
Target: "127.0.0.1:8082",
|
|
||||||
Remark: "333",
|
|
||||||
}
|
|
||||||
var b []byte
|
|
||||||
if b, err = c.ReadLen(16); err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if _, err := c.SendConfigInfo(config); err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if !c.GetAddStatus() {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if _, err := c.SendHostInfo(host); err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if !c.GetAddStatus() {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if _, err := c.SendTaskInfo(tunnel); err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if !c.GetAddStatus() {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
c.Close()
|
|
||||||
NewRPClient("127.0.0.1:8284", string(b), "tcp").Start()
|
|
||||||
}
|
|
|
@ -220,7 +220,10 @@ func NewConn(tp string, vkey string, server string, connType string, proxyUrl st
|
||||||
if _, err := c.Write([]byte(common.CONN_TEST)); err != nil {
|
if _, err := c.Write([]byte(common.CONN_TEST)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := c.Write([]byte(crypt.Md5(version.GetVersion()))); err != nil {
|
if err := c.WriteLenContent([]byte(version.GetVersion())); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := c.WriteLenContent([]byte(version.VERSION)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
b, err := c.GetShortContent(32)
|
b, err := c.GetShortContent(32)
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -31,6 +33,14 @@ type p2pBridge struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p2pBridge *p2pBridge) SendLinkInfo(clientId int, link *conn.Link, t *file.Tunnel) (target net.Conn, err error) {
|
func (p2pBridge *p2pBridge) SendLinkInfo(clientId int, link *conn.Link, t *file.Tunnel) (target net.Conn, err error) {
|
||||||
|
for i := 0; muxSession == nil; i++ {
|
||||||
|
if i >= 20 {
|
||||||
|
err = errors.New("p2pBridge:too many times to get muxSession")
|
||||||
|
logs.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
runtime.Gosched() // waiting for another goroutine establish the mux connection
|
||||||
|
}
|
||||||
nowConn, err := muxSession.NewConn()
|
nowConn, err := muxSession.NewConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
udpConn = nil
|
udpConn = nil
|
||||||
|
@ -158,6 +168,7 @@ func handleP2PVisitor(localTcpConn net.Conn, config *config.CommonConfig, l *con
|
||||||
if udpConn == nil {
|
if udpConn == nil {
|
||||||
logs.Notice("new conn, P2P can not penetrate successfully, traffic will be transferred through the server")
|
logs.Notice("new conn, P2P can not penetrate successfully, traffic will be transferred through the server")
|
||||||
handleSecret(localTcpConn, config, l)
|
handleSecret(localTcpConn, config, l)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
logs.Trace("start trying to connect with the server")
|
logs.Trace("start trying to connect with the server")
|
||||||
//TODO just support compress now because there is not tls file in client packages
|
//TODO just support compress now because there is not tls file in client packages
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"github.com/astaxie/beego/logs"
|
||||||
|
"github.com/cnlh/nps/client"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logs.SetLogger(logs.AdapterFile, `{"filename":"npc.log","daily":false,"maxlines":100000,"color":true}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
var status int
|
||||||
|
var closeBefore int
|
||||||
|
var cl *client.TRPClient
|
||||||
|
|
||||||
|
//export StartClientByVerifyKey
|
||||||
|
func StartClientByVerifyKey(serverAddr, verifyKey, connType, proxyUrl *C.char) int {
|
||||||
|
if cl != nil {
|
||||||
|
closeBefore = 1
|
||||||
|
cl.Close()
|
||||||
|
}
|
||||||
|
cl = client.NewRPClient(C.GoString(serverAddr), C.GoString(verifyKey), C.GoString(connType), C.GoString(proxyUrl), nil)
|
||||||
|
closeBefore = 0
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
status = 1
|
||||||
|
cl.Start()
|
||||||
|
status = 0
|
||||||
|
if closeBefore == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
//export GetClientStatus
|
||||||
|
func GetClientStatus() int {
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
|
//export CloseClient
|
||||||
|
func CloseClient() {
|
||||||
|
closeBefore = 1
|
||||||
|
cl.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Need a main function to make CGO compile package as C shared library
|
||||||
|
}
|
|
@ -18,7 +18,8 @@ import (
|
||||||
"github.com/cnlh/nps/server/connection"
|
"github.com/cnlh/nps/server/connection"
|
||||||
"github.com/cnlh/nps/server/test"
|
"github.com/cnlh/nps/server/test"
|
||||||
"github.com/cnlh/nps/server/tool"
|
"github.com/cnlh/nps/server/tool"
|
||||||
_ "github.com/cnlh/nps/web/routers"
|
|
||||||
|
"github.com/cnlh/nps/web/routers"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -29,6 +30,7 @@ var (
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
beego.LoadAppConfig("ini", filepath.Join(common.GetRunPath(), "conf", "nps.conf"))
|
beego.LoadAppConfig("ini", filepath.Join(common.GetRunPath(), "conf", "nps.conf"))
|
||||||
|
routers.Init()
|
||||||
if len(os.Args) > 1 {
|
if len(os.Args) > 1 {
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
case "test":
|
case "test":
|
||||||
|
|
|
@ -41,6 +41,9 @@ web_username=admin
|
||||||
web_password=123
|
web_password=123
|
||||||
web_port = 8080
|
web_port = 8080
|
||||||
web_ip=0.0.0.0
|
web_ip=0.0.0.0
|
||||||
|
web_base_url=
|
||||||
|
# if web under proxy use sub path. like http://host/nps need this.
|
||||||
|
#web_base_url=/nps
|
||||||
|
|
||||||
#Web API unauthenticated IP address(the len of auth_crypt_key must be 16)
|
#Web API unauthenticated IP address(the len of auth_crypt_key must be 16)
|
||||||
auth_key=test
|
auth_key=test
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -15,7 +15,7 @@ require (
|
||||||
github.com/panjf2000/ants/v2 v2.2.2
|
github.com/panjf2000/ants/v2 v2.2.2
|
||||||
github.com/pkg/errors v0.8.0
|
github.com/pkg/errors v0.8.0
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
|
||||||
github.com/shirou/gopsutil v2.18.12+incompatible
|
github.com/shirou/gopsutil v2.19.11+incompatible
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||||
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
|
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -55,6 +55,8 @@ github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||||
github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM=
|
github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM=
|
||||||
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
|
github.com/shirou/gopsutil v2.19.11+incompatible h1:lJHR0foqAjI4exXqWsU3DbH7bX1xvdhGdnXTIARA9W4=
|
||||||
|
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||||
github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||||
|
|
|
@ -6,6 +6,9 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -119,7 +122,8 @@ func (Self *BasePackager) Split() (strList []string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConnPackager struct { // Todo
|
type ConnPackager struct {
|
||||||
|
// Todo
|
||||||
ConnType uint8
|
ConnType uint8
|
||||||
BasePackager
|
BasePackager
|
||||||
}
|
}
|
||||||
|
@ -233,3 +237,206 @@ func (Self *MuxPackager) UnPack(reader io.Reader) (n uint16, err error) {
|
||||||
n += 5 //uint8 int32
|
n += 5 //uint8 int32
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ipV4 = 1
|
||||||
|
domainName = 3
|
||||||
|
ipV6 = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
type UDPHeader struct {
|
||||||
|
Rsv uint16
|
||||||
|
Frag uint8
|
||||||
|
Addr *Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUDPHeader(rsv uint16, frag uint8, addr *Addr) *UDPHeader {
|
||||||
|
return &UDPHeader{
|
||||||
|
Rsv: rsv,
|
||||||
|
Frag: frag,
|
||||||
|
Addr: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Addr struct {
|
||||||
|
Type uint8
|
||||||
|
Host string
|
||||||
|
Port uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (addr *Addr) String() string {
|
||||||
|
return net.JoinHostPort(addr.Host, strconv.Itoa(int(addr.Port)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (addr *Addr) Decode(b []byte) error {
|
||||||
|
addr.Type = b[0]
|
||||||
|
pos := 1
|
||||||
|
switch addr.Type {
|
||||||
|
case ipV4:
|
||||||
|
addr.Host = net.IP(b[pos:pos+net.IPv4len]).String()
|
||||||
|
pos += net.IPv4len
|
||||||
|
case ipV6:
|
||||||
|
addr.Host = net.IP(b[pos:pos+net.IPv6len]).String()
|
||||||
|
pos += net.IPv6len
|
||||||
|
case domainName:
|
||||||
|
addrlen := int(b[pos])
|
||||||
|
pos++
|
||||||
|
addr.Host = string(b[pos : pos+addrlen])
|
||||||
|
pos += addrlen
|
||||||
|
default:
|
||||||
|
return errors.New("decode error")
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.Port = binary.BigEndian.Uint16(b[pos:])
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (addr *Addr) Encode(b []byte) (int, error) {
|
||||||
|
b[0] = addr.Type
|
||||||
|
pos := 1
|
||||||
|
switch addr.Type {
|
||||||
|
case ipV4:
|
||||||
|
ip4 := net.ParseIP(addr.Host).To4()
|
||||||
|
if ip4 == nil {
|
||||||
|
ip4 = net.IPv4zero.To4()
|
||||||
|
}
|
||||||
|
pos += copy(b[pos:], ip4)
|
||||||
|
case domainName:
|
||||||
|
b[pos] = byte(len(addr.Host))
|
||||||
|
pos++
|
||||||
|
pos += copy(b[pos:], []byte(addr.Host))
|
||||||
|
case ipV6:
|
||||||
|
ip16 := net.ParseIP(addr.Host).To16()
|
||||||
|
if ip16 == nil {
|
||||||
|
ip16 = net.IPv6zero.To16()
|
||||||
|
}
|
||||||
|
pos += copy(b[pos:], ip16)
|
||||||
|
default:
|
||||||
|
b[0] = ipV4
|
||||||
|
copy(b[pos:pos+4], net.IPv4zero.To4())
|
||||||
|
pos += 4
|
||||||
|
}
|
||||||
|
binary.BigEndian.PutUint16(b[pos:], addr.Port)
|
||||||
|
pos += 2
|
||||||
|
|
||||||
|
return pos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *UDPHeader) Write(w io.Writer) error {
|
||||||
|
b := BufPoolUdp.Get().([]byte)
|
||||||
|
defer BufPoolUdp.Put(b)
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint16(b[:2], h.Rsv)
|
||||||
|
b[2] = h.Frag
|
||||||
|
|
||||||
|
addr := h.Addr
|
||||||
|
if addr == nil {
|
||||||
|
addr = &Addr{}
|
||||||
|
}
|
||||||
|
length, _ := addr.Encode(b[3:])
|
||||||
|
|
||||||
|
_, err := w.Write(b[:3+length])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type UDPDatagram struct {
|
||||||
|
Header *UDPHeader
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadUDPDatagram(r io.Reader) (*UDPDatagram, error) {
|
||||||
|
b := BufPoolUdp.Get().([]byte)
|
||||||
|
defer BufPoolUdp.Put(b)
|
||||||
|
|
||||||
|
// when r is a streaming (such as TCP connection), we may read more than the required data,
|
||||||
|
// but we don't know how to handle it. So we use io.ReadFull to instead of io.ReadAtLeast
|
||||||
|
// to make sure that no redundant data will be discarded.
|
||||||
|
n, err := io.ReadFull(r, b[:5])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
header := &UDPHeader{
|
||||||
|
Rsv: binary.BigEndian.Uint16(b[:2]),
|
||||||
|
Frag: b[2],
|
||||||
|
}
|
||||||
|
|
||||||
|
atype := b[3]
|
||||||
|
hlen := 0
|
||||||
|
switch atype {
|
||||||
|
case ipV4:
|
||||||
|
hlen = 10
|
||||||
|
case ipV6:
|
||||||
|
hlen = 22
|
||||||
|
case domainName:
|
||||||
|
hlen = 7 + int(b[4])
|
||||||
|
default:
|
||||||
|
return nil, errors.New("addr not support")
|
||||||
|
}
|
||||||
|
dlen := int(header.Rsv)
|
||||||
|
if dlen == 0 { // standard SOCKS5 UDP datagram
|
||||||
|
extra, err := ioutil.ReadAll(r) // we assume no redundant data
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
copy(b[n:], extra)
|
||||||
|
n += len(extra) // total length
|
||||||
|
dlen = n - hlen // data length
|
||||||
|
} else { // extended feature, for UDP over TCP, using reserved field as data length
|
||||||
|
if _, err := io.ReadFull(r, b[n:hlen+dlen]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
n = hlen + dlen
|
||||||
|
}
|
||||||
|
header.Addr = new(Addr)
|
||||||
|
if err := header.Addr.Decode(b[3:hlen]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := make([]byte, dlen)
|
||||||
|
copy(data, b[hlen:n])
|
||||||
|
d := &UDPDatagram{
|
||||||
|
Header: header,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUDPDatagram(header *UDPHeader, data []byte) *UDPDatagram {
|
||||||
|
return &UDPDatagram{
|
||||||
|
Header: header,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *UDPDatagram) Write(w io.Writer) error {
|
||||||
|
h := d.Header
|
||||||
|
if h == nil {
|
||||||
|
h = &UDPHeader{}
|
||||||
|
}
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
if err := h.Write(&buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := buf.Write(d.Data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := buf.WriteTo(w)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSocksAddr(addr net.Addr) *Addr {
|
||||||
|
host := "0.0.0.0"
|
||||||
|
port := 0
|
||||||
|
if addr != nil {
|
||||||
|
h, p, _ := net.SplitHostPort(addr.String())
|
||||||
|
host = h
|
||||||
|
port, _ = strconv.Atoi(p)
|
||||||
|
}
|
||||||
|
return &Addr{
|
||||||
|
Type: ipV4,
|
||||||
|
Host: host,
|
||||||
|
Port: uint16(port),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
const PoolSize = 64 * 1024
|
const PoolSize = 64 * 1024
|
||||||
const PoolSizeSmall = 100
|
const PoolSizeSmall = 100
|
||||||
const PoolSizeUdp = 1472
|
const PoolSizeUdp = 1472 + 200
|
||||||
const PoolSizeCopy = 32 << 10
|
const PoolSizeCopy = 32 << 10
|
||||||
const PoolSizeBuffer = 4096
|
const PoolSizeBuffer = 4096
|
||||||
const PoolSizeWindow = PoolSizeBuffer - 2 - 4 - 4 - 1
|
const PoolSizeWindow = PoolSizeBuffer - 2 - 4 - 4 - 1
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -396,3 +397,62 @@ func GetExtFromPath(path string) string {
|
||||||
}
|
}
|
||||||
return string(re.Find([]byte(s[0])))
|
return string(re.Find([]byte(s[0])))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var externalIp string
|
||||||
|
|
||||||
|
func GetExternalIp() string {
|
||||||
|
if externalIp != "" {
|
||||||
|
return externalIp
|
||||||
|
}
|
||||||
|
resp, err := http.Get("http://myexternalip.com/raw")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
content, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
externalIp = string(content)
|
||||||
|
return externalIp
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIntranetIp() (error, string) {
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, ""
|
||||||
|
}
|
||||||
|
for _, address := range addrs {
|
||||||
|
// 检查ip地址判断是否回环地址
|
||||||
|
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if ipnet.IP.To4() != nil {
|
||||||
|
return nil, ipnet.IP.To4().String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("get intranet ip error"), ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsPublicIP(IP net.IP) bool {
|
||||||
|
if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ip4 := IP.To4(); ip4 != nil {
|
||||||
|
switch true {
|
||||||
|
case ip4[0] == 10:
|
||||||
|
return false
|
||||||
|
case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
|
||||||
|
return false
|
||||||
|
case ip4[0] == 192 && ip4[1] == 168:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetServerIpByClientIp(clientIp net.IP) string {
|
||||||
|
if IsPublicIP(clientIp) {
|
||||||
|
return GetExternalIp()
|
||||||
|
}
|
||||||
|
_, ip := GetIntranetIp()
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (s *Conn) GetShortContent(l int) (b []byte, err error) {
|
||||||
|
|
||||||
//读取指定长度内容
|
//读取指定长度内容
|
||||||
func (s *Conn) ReadLen(cLen int, buf []byte) (int, error) {
|
func (s *Conn) ReadLen(cLen int, buf []byte) (int, error) {
|
||||||
if cLen > len(buf) {
|
if cLen > len(buf) || cLen <= 0 {
|
||||||
return 0, errors.New("长度错误" + strconv.Itoa(cLen))
|
return 0, errors.New("长度错误" + strconv.Itoa(cLen))
|
||||||
}
|
}
|
||||||
if n, err := io.ReadFull(s, buf[:cLen]); err != nil || n != cLen {
|
if n, err := io.ReadFull(s, buf[:cLen]); err != nil || n != cLen {
|
||||||
|
@ -124,8 +124,8 @@ func (s *Conn) SetAlive(tp string) {
|
||||||
case *net.TCPConn:
|
case *net.TCPConn:
|
||||||
conn := s.Conn.(*net.TCPConn)
|
conn := s.Conn.(*net.TCPConn)
|
||||||
conn.SetReadDeadline(time.Time{})
|
conn.SetReadDeadline(time.Time{})
|
||||||
conn.SetKeepAlive(true)
|
//conn.SetKeepAlive(false)
|
||||||
conn.SetKeepAlivePeriod(time.Duration(2 * time.Second))
|
//conn.SetKeepAlivePeriod(time.Duration(2 * time.Second))
|
||||||
case *mux.PortConn:
|
case *mux.PortConn:
|
||||||
s.Conn.(*mux.PortConn).SetReadDeadline(time.Time{})
|
s.Conn.(*mux.PortConn).SetReadDeadline(time.Time{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package conn
|
package conn
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
Password string
|
Password string
|
||||||
Conn *Conn
|
Conn *Conn
|
||||||
|
@ -19,9 +21,20 @@ type Link struct {
|
||||||
Compress bool
|
Compress bool
|
||||||
LocalProxy bool
|
LocalProxy bool
|
||||||
RemoteAddr string
|
RemoteAddr string
|
||||||
|
Option Options
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLink(connType string, host string, crypt bool, compress bool, remoteAddr string, localProxy bool) *Link {
|
type Option func(*Options)
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
Timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultTimeOut = time.Second * 5
|
||||||
|
|
||||||
|
func NewLink(connType string, host string, crypt bool, compress bool, remoteAddr string, localProxy bool, opts ...Option) *Link {
|
||||||
|
options := newOptions(opts...)
|
||||||
|
|
||||||
return &Link{
|
return &Link{
|
||||||
RemoteAddr: remoteAddr,
|
RemoteAddr: remoteAddr,
|
||||||
ConnType: connType,
|
ConnType: connType,
|
||||||
|
@ -29,5 +42,22 @@ func NewLink(connType string, host string, crypt bool, compress bool, remoteAddr
|
||||||
Crypt: crypt,
|
Crypt: crypt,
|
||||||
Compress: compress,
|
Compress: compress,
|
||||||
LocalProxy: localProxy,
|
LocalProxy: localProxy,
|
||||||
|
Option: options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOptions(opts ...Option) Options {
|
||||||
|
opt := Options{
|
||||||
|
Timeout: defaultTimeOut,
|
||||||
|
}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&opt)
|
||||||
|
}
|
||||||
|
return opt
|
||||||
|
}
|
||||||
|
|
||||||
|
func LinkTimeout(t time.Duration) Option {
|
||||||
|
return func(opt *Options) {
|
||||||
|
opt.Timeout = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package conn
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/cnlh/nps/lib/common"
|
|
||||||
"github.com/golang/snappy"
|
"github.com/golang/snappy"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,13 +31,7 @@ func (s *SnappyConn) Write(b []byte) (n int, err error) {
|
||||||
|
|
||||||
//snappy压缩读
|
//snappy压缩读
|
||||||
func (s *SnappyConn) Read(b []byte) (n int, err error) {
|
func (s *SnappyConn) Read(b []byte) (n int, err error) {
|
||||||
buf := common.BufPool.Get().([]byte)
|
return s.r.Read(b)
|
||||||
defer common.BufPool.Put(buf)
|
|
||||||
if n, err = s.r.Read(buf); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
copy(b, buf[:n])
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SnappyConn) Close() error {
|
func (s *SnappyConn) Close() error {
|
||||||
|
|
|
@ -50,6 +50,7 @@ type Client struct {
|
||||||
WebPassword string //the password of web login
|
WebPassword string //the password of web login
|
||||||
ConfigConnAllow bool //is allow connected by config file
|
ConfigConnAllow bool //is allow connected by config file
|
||||||
MaxTunnelNum int
|
MaxTunnelNum int
|
||||||
|
Version string
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -499,8 +499,16 @@ start:
|
||||||
|
|
||||||
func (Self *SendWindow) waitReceiveWindow() (err error) {
|
func (Self *SendWindow) waitReceiveWindow() (err error) {
|
||||||
t := Self.timeout.Sub(time.Now())
|
t := Self.timeout.Sub(time.Now())
|
||||||
if t < 0 {
|
if t < 0 { // not set the timeout, wait for it as long as connection close
|
||||||
t = time.Minute * 5
|
select {
|
||||||
|
case _, ok := <-Self.setSizeCh:
|
||||||
|
if !ok {
|
||||||
|
return errors.New("conn.writeWindow: window closed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case <-Self.closeOpCh:
|
||||||
|
return errors.New("conn.writeWindow: window closed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
timer := time.NewTimer(t)
|
timer := time.NewTimer(t)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
|
@ -300,8 +300,14 @@ func (Self *ReceiveWindowQueue) waitPush() (err error) {
|
||||||
//logs.Warn("wait push")
|
//logs.Warn("wait push")
|
||||||
//defer logs.Warn("wait push finish")
|
//defer logs.Warn("wait push finish")
|
||||||
t := Self.timeout.Sub(time.Now())
|
t := Self.timeout.Sub(time.Now())
|
||||||
if t <= 0 {
|
if t <= 0 { // not set the timeout, so wait for it without timeout, just like a tcp connection
|
||||||
t = time.Minute * 5
|
select {
|
||||||
|
case <-Self.readOp:
|
||||||
|
return nil
|
||||||
|
case <-Self.stopOp:
|
||||||
|
err = io.EOF
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
timer := time.NewTimer(t)
|
timer := time.NewTimer(t)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package version
|
package version
|
||||||
|
|
||||||
const VERSION = "0.24.0"
|
const VERSION = "0.25.0"
|
||||||
|
|
||||||
// Compulsory minimum version, Minimum downward compatibility to this version
|
// Compulsory minimum version, Minimum downward compatibility to this version
|
||||||
func GetVersion() string {
|
func GetVersion() string {
|
||||||
return "0.24.0"
|
return "0.25.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,11 +171,11 @@ reset:
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for {
|
for {
|
||||||
if resp, err := http.ReadResponse(bufio.NewReader(connClient), r); err != nil {
|
if resp, err := http.ReadResponse(bufio.NewReader(connClient), r); err != nil || resp == nil {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
//if the cache is start and the response is in the extension,store the response to the cache list
|
//if the cache is start and the response is in the extension,store the response to the cache list
|
||||||
if s.useCache && strings.Contains(r.URL.Path, ".") {
|
if s.useCache && r.URL != nil && strings.Contains(r.URL.Path, ".") {
|
||||||
b, err := httputil.DumpResponse(resp, true)
|
b, err := httputil.DumpResponse(resp, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -154,27 +154,129 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) {
|
||||||
// passive mode
|
// passive mode
|
||||||
func (s *Sock5ModeServer) handleBind(c net.Conn) {
|
func (s *Sock5ModeServer) handleBind(c net.Conn) {
|
||||||
}
|
}
|
||||||
|
func (s *Sock5ModeServer) sendUdpReply(writeConn net.Conn, c net.Conn, rep uint8, serverIp string) {
|
||||||
|
reply := []byte{
|
||||||
|
5,
|
||||||
|
rep,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
}
|
||||||
|
localHost, localPort, _ := net.SplitHostPort(c.LocalAddr().String())
|
||||||
|
localHost = serverIp
|
||||||
|
ipBytes := net.ParseIP(localHost).To4()
|
||||||
|
nPort, _ := strconv.Atoi(localPort)
|
||||||
|
reply = append(reply, ipBytes...)
|
||||||
|
portBytes := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(portBytes, uint16(nPort))
|
||||||
|
reply = append(reply, portBytes...)
|
||||||
|
writeConn.Write(reply)
|
||||||
|
|
||||||
//udp
|
|
||||||
func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
|
||||||
/*
|
|
||||||
+----+------+------+----------+----------+----------+
|
|
||||||
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
|
||||||
+----+------+------+----------+----------+----------+
|
|
||||||
| 2 | 1 | 1 | Variable | 2 | Variable |
|
|
||||||
+----+------+------+----------+----------+----------+
|
|
||||||
*/
|
|
||||||
buf := make([]byte, 3)
|
|
||||||
c.Read(buf)
|
|
||||||
// relay udp datagram silently, without any notification to the requesting client
|
|
||||||
if buf[2] != 0 {
|
|
||||||
// does not support fragmentation, drop it
|
|
||||||
logs.Warn("does not support fragmentation, drop")
|
|
||||||
dummy := make([]byte, maxUDPPacketSize)
|
|
||||||
c.Read(dummy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.doConnect(c, associateMethod)
|
func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||||
|
defer c.Close()
|
||||||
|
addrType := make([]byte, 1)
|
||||||
|
c.Read(addrType)
|
||||||
|
var host string
|
||||||
|
switch addrType[0] {
|
||||||
|
case ipV4:
|
||||||
|
ipv4 := make(net.IP, net.IPv4len)
|
||||||
|
c.Read(ipv4)
|
||||||
|
host = ipv4.String()
|
||||||
|
case ipV6:
|
||||||
|
ipv6 := make(net.IP, net.IPv6len)
|
||||||
|
c.Read(ipv6)
|
||||||
|
host = ipv6.String()
|
||||||
|
case domainName:
|
||||||
|
var domainLen uint8
|
||||||
|
binary.Read(c, binary.BigEndian, &domainLen)
|
||||||
|
domain := make([]byte, domainLen)
|
||||||
|
c.Read(domain)
|
||||||
|
host = string(domain)
|
||||||
|
default:
|
||||||
|
s.sendReply(c, addrTypeNotSupported)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//读取端口
|
||||||
|
var port uint16
|
||||||
|
binary.Read(c, binary.BigEndian, &port)
|
||||||
|
logs.Warn(host, string(port))
|
||||||
|
replyAddr, err := net.ResolveUDPAddr("udp", s.task.ServerIp+":0")
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("build local reply addr error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reply, err := net.ListenUDP("udp", replyAddr)
|
||||||
|
if err != nil {
|
||||||
|
s.sendReply(c, addrTypeNotSupported)
|
||||||
|
logs.Error("listen local reply udp port error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// reply the local addr
|
||||||
|
s.sendUdpReply(c, reply, succeeded, common.GetServerIpByClientIp(c.RemoteAddr().(*net.TCPAddr).IP))
|
||||||
|
defer reply.Close()
|
||||||
|
// new a tunnel to client
|
||||||
|
link := conn.NewLink("udp5", "", s.task.Client.Cnf.Crypt, s.task.Client.Cnf.Compress, c.RemoteAddr().String(), false)
|
||||||
|
target, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, s.task)
|
||||||
|
if err != nil {
|
||||||
|
logs.Warn("get connection from client id %d error %s", s.task.Client.Id, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var clientAddr net.Addr
|
||||||
|
// copy buffer
|
||||||
|
go func() {
|
||||||
|
b := common.BufPoolUdp.Get().([]byte)
|
||||||
|
defer common.BufPoolUdp.Put(b)
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, laddr, err := reply.ReadFrom(b)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("read data from %s err %s", reply.LocalAddr().String(), err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if clientAddr == nil {
|
||||||
|
clientAddr = laddr
|
||||||
|
}
|
||||||
|
if _, err := target.Write(b[:n]); err != nil {
|
||||||
|
logs.Error("write data to client error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var l int32
|
||||||
|
b := common.BufPoolUdp.Get().([]byte)
|
||||||
|
defer common.BufPoolUdp.Put(b)
|
||||||
|
defer c.Close()
|
||||||
|
for {
|
||||||
|
if err := binary.Read(target, binary.LittleEndian, &l); err != nil || l >= common.PoolSizeUdp || l <= 0 {
|
||||||
|
logs.Warn("read len bytes error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binary.Read(target, binary.LittleEndian, b[:l])
|
||||||
|
if err != nil {
|
||||||
|
logs.Warn("read data form client error", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := reply.WriteTo(b[:l], clientAddr); err != nil {
|
||||||
|
logs.Warn("write data to user ", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
b := common.BufPoolUdp.Get().([]byte)
|
||||||
|
defer common.BufPoolUdp.Put(b)
|
||||||
|
for {
|
||||||
|
_, err := c.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
c.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//new conn
|
//new conn
|
||||||
|
|
|
@ -63,7 +63,7 @@ func (s *WebServer) Start() error {
|
||||||
<-stop
|
<-stop
|
||||||
}
|
}
|
||||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||||
beego.SetStaticPath("/static", filepath.Join(common.GetRunPath(), "web", "static"))
|
beego.SetStaticPath(beego.AppConfig.String("web_base_url")+"/static", filepath.Join(common.GetRunPath(), "web", "static"))
|
||||||
beego.SetViewsPath(filepath.Join(common.GetRunPath(), "web", "views"))
|
beego.SetViewsPath(filepath.Join(common.GetRunPath(), "web", "views"))
|
||||||
if l, err := connection.GetWebManagerListener(); err == nil {
|
if l, err := connection.GetWebManagerListener(); err == nil {
|
||||||
beego.InitBeforeHTTPRun()
|
beego.InitBeforeHTTPRun()
|
||||||
|
|
|
@ -2,6 +2,7 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/cnlh/nps/lib/version"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -271,8 +272,9 @@ func GetClientList(start, length int, search, sort, order string, clientId int)
|
||||||
func dealClientData() {
|
func dealClientData() {
|
||||||
file.GetDb().JsonDb.Clients.Range(func(key, value interface{}) bool {
|
file.GetDb().JsonDb.Clients.Range(func(key, value interface{}) bool {
|
||||||
v := value.(*file.Client)
|
v := value.(*file.Client)
|
||||||
if _, ok := Bridge.Client.Load(v.Id); ok {
|
if vv, ok := Bridge.Client.Load(v.Id); ok {
|
||||||
v.IsConnect = true
|
v.IsConnect = true
|
||||||
|
v.Version = vv.(*bridge.Client).Version
|
||||||
} else {
|
} else {
|
||||||
v.IsConnect = false
|
v.IsConnect = false
|
||||||
}
|
}
|
||||||
|
@ -338,6 +340,7 @@ func DelClientConnect(clientId int) {
|
||||||
|
|
||||||
func GetDashboardData() map[string]interface{} {
|
func GetDashboardData() map[string]interface{} {
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
|
data["version"] = version.VERSION
|
||||||
data["hostCount"] = common.GeSynctMapLen(file.GetDb().JsonDb.Hosts)
|
data["hostCount"] = common.GeSynctMapLen(file.GetDb().JsonDb.Hosts)
|
||||||
data["clientCount"] = common.GeSynctMapLen(file.GetDb().JsonDb.Clients) - 1 //Remove the public key client
|
data["clientCount"] = common.GeSynctMapLen(file.GetDb().JsonDb.Clients) - 1 //Remove the public key client
|
||||||
dealClientData()
|
dealClientData()
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#/bash/sh
|
||||||
|
echo "start upgrading to the latest version"
|
||||||
|
if [ $1 == "latest" ]
|
||||||
|
then
|
||||||
|
version=`wget -qO- -t1 -T2 "https://api.github.com/repos/cnlh/nps/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g'`
|
||||||
|
else
|
||||||
|
version=$1
|
||||||
|
fi
|
||||||
|
echo "the current latest version is "$version""
|
||||||
|
download_base_url=https://github.com/cnlh/nps/releases/download/$version/
|
||||||
|
|
||||||
|
if [ $4 ]
|
||||||
|
then
|
||||||
|
filename=""$2"_"$3"_v"$4"_"server".tar.gz"
|
||||||
|
else
|
||||||
|
filename=""$2"_"$3"_"server".tar.gz"
|
||||||
|
fi
|
||||||
|
complete_download_url=""$download_base_url""$filename""
|
||||||
|
echo "start download file from "$complete_download_url""
|
||||||
|
|
||||||
|
dir_name=`echo $RANDOM`
|
||||||
|
mkdir $dir_name && cd $dir_name
|
||||||
|
wget $complete_download_url >/dev/null 2>&1
|
||||||
|
if [ ! -f "$filename" ]; then
|
||||||
|
echo "download file failed!"
|
||||||
|
rm -rf $dir_name
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "start extracting files"
|
||||||
|
mkdir nps
|
||||||
|
tar -xvf $filename -C ./nps >/dev/null 2>&1
|
||||||
|
cd nps
|
||||||
|
|
||||||
|
if [ -f "../../nps" ]; then
|
||||||
|
echo "replace "../../nps"!"
|
||||||
|
cp -rf nps ../../
|
||||||
|
fi
|
||||||
|
|
||||||
|
usr_dir=`which nps`
|
||||||
|
|
||||||
|
if [ -f "$usr_dir" ]; then
|
||||||
|
echo "replace "$usr_dir"!"
|
||||||
|
cp -rf nps $usr_dir
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ../../ && rm -rf $dir_name
|
||||||
|
|
||||||
|
echo "update complete!"
|
||||||
|
echo -e "\033[32m please restart nps \033[0m"
|
|
@ -22,6 +22,7 @@ type BaseController struct {
|
||||||
|
|
||||||
//初始化参数
|
//初始化参数
|
||||||
func (s *BaseController) Prepare() {
|
func (s *BaseController) Prepare() {
|
||||||
|
s.Data["web_base_url"] = beego.AppConfig.String("web_base_url")
|
||||||
controllerName, actionName := s.GetControllerAndAction()
|
controllerName, actionName := s.GetControllerAndAction()
|
||||||
s.controllerName = strings.ToLower(controllerName[0 : len(controllerName)-10])
|
s.controllerName = strings.ToLower(controllerName[0 : len(controllerName)-10])
|
||||||
s.actionName = strings.ToLower(actionName)
|
s.actionName = strings.ToLower(actionName)
|
||||||
|
@ -34,7 +35,7 @@ func (s *BaseController) Prepare() {
|
||||||
timeNowUnix := time.Now().Unix()
|
timeNowUnix := time.Now().Unix()
|
||||||
if !((math.Abs(float64(timeNowUnix-int64(timestamp))) <= 20) && (crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key)) {
|
if !((math.Abs(float64(timeNowUnix-int64(timestamp))) <= 20) && (crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key)) {
|
||||||
if s.GetSession("auth") != true {
|
if s.GetSession("auth") != true {
|
||||||
s.Redirect("/login/index", 302)
|
s.Redirect(beego.AppConfig.String("web_base_url")+"/login/index", 302)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.GetSession("isAdmin") != nil && !s.GetSession("isAdmin").(bool) {
|
if s.GetSession("isAdmin") != nil && !s.GetSession("isAdmin").(bool) {
|
||||||
|
@ -60,6 +61,7 @@ func (s *BaseController) Prepare() {
|
||||||
|
|
||||||
//加载模板
|
//加载模板
|
||||||
func (s *BaseController) display(tpl ...string) {
|
func (s *BaseController) display(tpl ...string) {
|
||||||
|
s.Data["web_base_url"] = beego.AppConfig.String("web_base_url")
|
||||||
var tplname string
|
var tplname string
|
||||||
if s.Data["menu"] == nil {
|
if s.Data["menu"] == nil {
|
||||||
s.Data["menu"] = s.actionName
|
s.Data["menu"] = s.actionName
|
||||||
|
@ -83,6 +85,7 @@ func (s *BaseController) display(tpl ...string) {
|
||||||
|
|
||||||
//错误
|
//错误
|
||||||
func (s *BaseController) error() {
|
func (s *BaseController) error() {
|
||||||
|
s.Data["web_base_url"] = beego.AppConfig.String("web_base_url")
|
||||||
s.Layout = "public/layout.html"
|
s.Layout = "public/layout.html"
|
||||||
s.TplName = "public/error.html"
|
s.TplName = "public/error.html"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/server"
|
"github.com/cnlh/nps/server"
|
||||||
"github.com/cnlh/nps/server/tool"
|
"github.com/cnlh/nps/server/tool"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IndexController struct {
|
type IndexController struct {
|
||||||
|
@ -11,6 +13,7 @@ type IndexController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IndexController) Index() {
|
func (s *IndexController) Index() {
|
||||||
|
s.Data["web_base_url"] = beego.AppConfig.String("web_base_url")
|
||||||
s.Data["data"] = server.GetDashboardData()
|
s.Data["data"] = server.GetDashboardData()
|
||||||
s.SetInfo("dashboard")
|
s.SetInfo("dashboard")
|
||||||
s.display("index/index")
|
s.display("index/index")
|
||||||
|
|
|
@ -14,6 +14,7 @@ type LoginController struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LoginController) Index() {
|
func (self *LoginController) Index() {
|
||||||
|
self.Data["web_base_url"] = beego.AppConfig.String("web_base_url")
|
||||||
self.Data["register_allow"], _ = beego.AppConfig.Bool("allow_user_register")
|
self.Data["register_allow"], _ = beego.AppConfig.Bool("allow_user_register")
|
||||||
self.TplName = "login/index.html"
|
self.TplName = "login/index.html"
|
||||||
}
|
}
|
||||||
|
@ -60,6 +61,7 @@ func (self *LoginController) Verify() {
|
||||||
}
|
}
|
||||||
func (self *LoginController) Register() {
|
func (self *LoginController) Register() {
|
||||||
if self.Ctx.Request.Method == "GET" {
|
if self.Ctx.Request.Method == "GET" {
|
||||||
|
self.Data["web_base_url"] = beego.AppConfig.String("web_base_url")
|
||||||
self.TplName = "login/register.html"
|
self.TplName = "login/register.html"
|
||||||
} else {
|
} else {
|
||||||
if b, err := beego.AppConfig.Bool("allow_user_register"); err != nil || !b {
|
if b, err := beego.AppConfig.Bool("allow_user_register"); err != nil || !b {
|
||||||
|
@ -91,5 +93,5 @@ func (self *LoginController) Register() {
|
||||||
|
|
||||||
func (self *LoginController) Out() {
|
func (self *LoginController) Out() {
|
||||||
self.SetSession("auth", false)
|
self.SetSession("auth", false)
|
||||||
self.Redirect("/login/index", 302)
|
self.Redirect(beego.AppConfig.String("web_base_url")+"/login/index", 302)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,22 @@ import (
|
||||||
"github.com/cnlh/nps/web/controllers"
|
"github.com/cnlh/nps/web/controllers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func Init() {
|
||||||
|
web_base_url := beego.AppConfig.String("web_base_url")
|
||||||
|
if len(web_base_url) > 0 {
|
||||||
|
ns := beego.NewNamespace(web_base_url,
|
||||||
|
beego.NSRouter("/", &controllers.IndexController{}, "*:Index"),
|
||||||
|
beego.NSAutoRouter(&controllers.IndexController{}),
|
||||||
|
beego.NSAutoRouter(&controllers.LoginController{}),
|
||||||
|
beego.NSAutoRouter(&controllers.ClientController{}),
|
||||||
|
beego.NSAutoRouter(&controllers.AuthController{}),
|
||||||
|
)
|
||||||
|
beego.AddNamespace(ns)
|
||||||
|
} else {
|
||||||
beego.Router("/", &controllers.IndexController{}, "*:Index")
|
beego.Router("/", &controllers.IndexController{}, "*:Index")
|
||||||
beego.AutoRouter(&controllers.IndexController{})
|
beego.AutoRouter(&controllers.IndexController{})
|
||||||
beego.AutoRouter(&controllers.LoginController{})
|
beego.AutoRouter(&controllers.LoginController{})
|
||||||
beego.AutoRouter(&controllers.ClientController{})
|
beego.AutoRouter(&controllers.ClientController{})
|
||||||
beego.AutoRouter(&controllers.AuthController{})
|
beego.AutoRouter(&controllers.AuthController{})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
url: defaults.file,
|
url: window.nps.web_base_url + defaults.file,
|
||||||
dataType: "xml",
|
dataType: "xml",
|
||||||
success: function (xml) {
|
success: function (xml) {
|
||||||
$(xml).find('text').each(function () {
|
$(xml).find('text').each(function () {
|
||||||
|
|
|
@ -134,7 +134,7 @@
|
||||||
$("#add").on("click", function () {
|
$("#add").on("click", function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/client/add",
|
url: "{{.web_base_url}}/client/add",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
$("#add").on("click", function () {
|
$("#add").on("click", function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/client/edit",
|
url: "{{.web_base_url}}/client/edit",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
<a href="/client/add" class="btn btn-primary dim" type="button" langtag="info-new">新增</a>
|
<a href="{{.web_base_url}}/client/add" class="btn btn-primary dim" type="button" langtag="info-new">新增</a>
|
||||||
</div>
|
</div>
|
||||||
<table id="taskList_table" class="table-striped table-hover"
|
<table id="taskList_table" class="table-striped table-hover"
|
||||||
data-mobile-responsive="true"></table>
|
data-mobile-responsive="true"></table>
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
if (confirm("Are you sure you want to delete it??")) {
|
if (confirm("Are you sure you want to delete it??")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/client/del",
|
url: "{{.web_base_url}}/client/del",
|
||||||
data: {"id": id},
|
data: {"id": id},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
if (confirm("Are you sure you want to start it??")) {
|
if (confirm("Are you sure you want to start it??")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/client/changestatus",
|
url: "{{.web_base_url}}/client/changestatus",
|
||||||
data: {"id": id, "status": 1},
|
data: {"id": id, "status": 1},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
if (confirm("Are you sure you want to stop it?")) {
|
if (confirm("Are you sure you want to stop it?")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/client/changestatus",
|
url: "{{.web_base_url}}/client/changestatus",
|
||||||
data: {
|
data: {
|
||||||
"id": id, "status": 0
|
"id": id, "status": 0
|
||||||
},
|
},
|
||||||
|
@ -90,26 +90,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit(id) {
|
function edit(id) {
|
||||||
window.location.href = "/client/edit?id=" + id
|
window.location.href = "{{.web_base_url}}/client/edit?id=" + id
|
||||||
}
|
}
|
||||||
|
|
||||||
function add() {
|
function add() {
|
||||||
window.location.href = "/client/add"
|
window.location.href = "{{.web_base_url}}/client/add"
|
||||||
}
|
}
|
||||||
|
|
||||||
function tunnel(id) {
|
function tunnel(id) {
|
||||||
window.location.href = "/index/all?client_id=" + id
|
window.location.href = "{{.web_base_url}}/index/all?client_id=" + id
|
||||||
}
|
}
|
||||||
|
|
||||||
function host(id) {
|
function host(id) {
|
||||||
window.location.href = "/index/hostlist?client_id=" + id
|
window.location.href = "{{.web_base_url}}/index/hostlist?client_id=" + id
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bootstrap table*/
|
/*bootstrap table*/
|
||||||
$('#table').bootstrapTable({
|
$('#table').bootstrapTable({
|
||||||
toolbar: "#toolbar",
|
toolbar: "#toolbar",
|
||||||
method: 'post', // 服务器数据的请求方式 get or post
|
method: 'post', // 服务器数据的请求方式 get or post
|
||||||
url: "/client/list", // 服务器数据的加载地址
|
url: "{{.web_base_url}}/client/list", // 服务器数据的加载地址
|
||||||
contentType: "application/x-www-form-urlencoded",
|
contentType: "application/x-www-form-urlencoded",
|
||||||
striped: true, // 设置为true会有隔行变色效果
|
striped: true, // 设置为true会有隔行变色效果
|
||||||
search: true,
|
search: true,
|
||||||
|
@ -150,6 +150,11 @@
|
||||||
title: 'remark',//标题
|
title: 'remark',//标题
|
||||||
visible: true,//false表示不显示
|
visible: true,//false表示不显示
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'Version',//域值
|
||||||
|
title: 'version',//标题
|
||||||
|
visible: true,//false表示不显示
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'VerifyKey',//域值
|
field: 'VerifyKey',//域值
|
||||||
title: 'vkey',//标题
|
title: 'vkey',//标题
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
$("#add").on("click", function () {
|
$("#add").on("click", function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/add",
|
url: "{{.web_base_url}}/index/add",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
|
|
@ -160,7 +160,7 @@
|
||||||
$("#add").on("click", function () {
|
$("#add").on("click", function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/edit",
|
url: "{{.web_base_url}}/index/edit",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
|
|
@ -112,7 +112,7 @@
|
||||||
$("#add").on("click", function () {
|
$("#add").on("click", function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/addhost",
|
url: "{{.web_base_url}}/index/addhost",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
|
|
@ -116,7 +116,7 @@
|
||||||
$("#add").on("click", function () {
|
$("#add").on("click", function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/edithost",
|
url: "{{.web_base_url}}/index/edithost",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
<a href="/index/addhost?vkey={{.task_id}}&client_id={{.client_id}}"
|
<a href="{{.web_base_url}}/index/addhost?vkey={{.task_id}}&client_id={{.client_id}}"
|
||||||
class="btn btn-primary dim"
|
class="btn btn-primary dim"
|
||||||
type="button" langtag="info-new">新增</a>
|
type="button" langtag="info-new">新增</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -158,7 +158,7 @@
|
||||||
if (confirm("Are you sure you want to delete it??")) {
|
if (confirm("Are you sure you want to delete it??")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/delhost",
|
url: "{{.web_base_url}}/index/delhost",
|
||||||
data: {"id": id},
|
data: {"id": id},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
@ -171,7 +171,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit(id) {
|
function edit(id) {
|
||||||
window.location.href = "/index/edithost?id=" + id
|
window.location.href = "{{.web_base_url}}/index/edithost?id=" + id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="list-group-item ">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<strong>服务端版本</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 text-right">
|
||||||
|
<strong>{{.data.version}}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<div id="toolbar">
|
<div id="toolbar">
|
||||||
<a href="/index/add?type={{.type}}&client_id={{.client_id}}" class="btn btn-primary dim"
|
<a href="{{.web_base_url}}/index/add?type={{.type}}&client_id={{.client_id}}" class="btn btn-primary dim"
|
||||||
type="button" langtag="info-new">新增</a>
|
type="button" langtag="info-new">新增</a>
|
||||||
</div>
|
</div>
|
||||||
<table id="taskList_table" class="table-striped table-hover"
|
<table id="taskList_table" class="table-striped table-hover"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
$('#table').bootstrapTable({
|
$('#table').bootstrapTable({
|
||||||
toolbar: "#toolbar",
|
toolbar: "#toolbar",
|
||||||
method: 'post', // 服务器数据的请求方式 get or post
|
method: 'post', // 服务器数据的请求方式 get or post
|
||||||
url: "/index/gettunnel", // 服务器数据的加载地址
|
url: "{{.web_base_url}}/index/gettunnel", // 服务器数据的加载地址
|
||||||
queryParams: function (params) {
|
queryParams: function (params) {
|
||||||
return {
|
return {
|
||||||
"offset": params.offset,
|
"offset": params.offset,
|
||||||
|
@ -191,7 +191,7 @@
|
||||||
if (confirm("Are you sure you want to delete it??")) {
|
if (confirm("Are you sure you want to delete it??")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/del",
|
url: "{{.web_base_url}}/index/del",
|
||||||
data: {"id": id},
|
data: {"id": id},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
@ -207,7 +207,7 @@
|
||||||
if (confirm("Are you sure you want to start it??")) {
|
if (confirm("Are you sure you want to start it??")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/start",
|
url: "{{.web_base_url}}/index/start",
|
||||||
data: {"id": id},
|
data: {"id": id},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
@ -223,7 +223,7 @@
|
||||||
if (confirm("Are you sure you want to stop it??")) {
|
if (confirm("Are you sure you want to stop it??")) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/index/stop",
|
url: "{{.web_base_url}}/index/stop",
|
||||||
data: {"id": id},
|
data: {"id": id},
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit(id) {
|
function edit(id) {
|
||||||
window.location.href = "/index/edit?id=" + id
|
window.location.href = "{{.web_base_url}}/index/edit?id=" + id
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
|
|
||||||
<title>nps admin login</title>
|
<title>nps admin login</title>
|
||||||
|
|
||||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
||||||
|
|
||||||
<link href="/static/css/style.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/css/style.css" rel="stylesheet">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
</div>
|
</div>
|
||||||
<button onclick="login()" class="btn btn-primary block full-width m-b">login</button>
|
<button onclick="login()" class="btn btn-primary block full-width m-b">login</button>
|
||||||
{{if eq true .register_allow}}
|
{{if eq true .register_allow}}
|
||||||
<a class="btn btn-sm btn-white btn-block" href="/login/register">register</a>
|
<a class="btn btn-sm btn-white btn-block" href="{{.web_base_url}}/login/register">register</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
<script src="/static/js/jquery-2.1.1.js"></script>
|
<script src="{{.web_base_url}}/static/js/jquery-2.1.1.js"></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@
|
||||||
function login() {
|
function login() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/login/verify",
|
url: "{{.web_base_url}}/login/verify",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
if (res.status) {
|
if (res.status) {
|
||||||
window.location.href = "/index/index"
|
window.location.href = "{{.web_base_url}}/index/index"
|
||||||
} else {
|
} else {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
|
|
||||||
<title>nps register</title>
|
<title>nps register</title>
|
||||||
|
|
||||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
||||||
|
|
||||||
<link href="/static/css/style.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/css/style.css" rel="stylesheet">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -34,22 +34,22 @@
|
||||||
</div>
|
</div>
|
||||||
<button onclick="register()" type="submit" class="btn btn-primary block full-width m-b">register</button>
|
<button onclick="register()" type="submit" class="btn btn-primary block full-width m-b">register</button>
|
||||||
|
|
||||||
<a class="btn btn-sm btn-white btn-block" href="/login/index">login</a>
|
<a class="btn btn-sm btn-white btn-block" href="{{.web_base_url}}/login/index">login</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/jquery-2.1.1.js"></script>
|
<script src="{{.web_base_url}}/static/js/jquery-2.1.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function register() {
|
function register() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "/login/register",
|
url: "{{.web_base_url}}/login/register",
|
||||||
data: $("form").serializeArray(),
|
data: $("form").serializeArray(),
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
alert(res.msg)
|
alert(res.msg)
|
||||||
if (res.status) {
|
if (res.status) {
|
||||||
window.location.href = "/login/index"
|
window.location.href = "{{.web_base_url}}/login/index"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,22 +9,22 @@
|
||||||
|
|
||||||
<title>nps admin</title>
|
<title>nps admin</title>
|
||||||
|
|
||||||
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/font-awesome/css/font-awesome.css" rel="stylesheet">
|
||||||
<link href="/static/css/style.css" rel="stylesheet">
|
<link href="{{.web_base_url}}/static/css/style.css" rel="stylesheet">
|
||||||
<script src="/static/js/main.js"></script>
|
<script src="{{.web_base_url}}/static/js/main.js"></script>
|
||||||
<!-- Mainly scripts -->
|
<!-- Mainly scripts -->
|
||||||
<script src="/static/js/jquery-2.1.1.js"></script>
|
<script src="{{.web_base_url}}/static/js/jquery-2.1.1.js"></script>
|
||||||
<script src="/static/js/bootstrap.min.js"></script>
|
<script src="{{.web_base_url}}/static/js/bootstrap.min.js"></script>
|
||||||
<script src="/static/js/echarts.min.js"></script>
|
<script src="{{.web_base_url}}/static/js/echarts.min.js"></script>
|
||||||
<!-- Latest compiled and minified CSS -->
|
<!-- Latest compiled and minified CSS -->
|
||||||
<link rel="stylesheet" href="/static/css/bootstrap-table.min.css">
|
<link rel="stylesheet" href="{{.web_base_url}}/static/css/bootstrap-table.min.css">
|
||||||
|
|
||||||
<!-- Latest compiled and minified JavaScript -->
|
<!-- Latest compiled and minified JavaScript -->
|
||||||
<script src="/static/js/bootstrap-table.min.js"></script>
|
<script src="{{.web_base_url}}/static/js/bootstrap-table.min.js"></script>
|
||||||
<script src="/static/js/inspinia.js"></script>
|
<script src="{{.web_base_url}}/static/js/inspinia.js"></script>
|
||||||
<!-- Latest compiled and minified Locales -->
|
<!-- Latest compiled and minified Locales -->
|
||||||
<script src="/static/js/langchange.js" type="text/javascript"></script>
|
<script src="{{.web_base_url}}/static/js/langchange.js" type="text/javascript"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
<ul class="nav metismenu" id="side-menu">
|
<ul class="nav metismenu" id="side-menu">
|
||||||
<li class="nav-header">
|
<li class="nav-header">
|
||||||
<div class="dropdown profile-element"> <span>
|
<div class="dropdown profile-element"> <span>
|
||||||
{{/*<img alt="image" class="img-circle" src="/static/img/profile_small.jpg"/>*/}}
|
{{/*<img alt="image" class="img-circle" src="{{.web_base_url}}/static/img/profile_small.jpg"/>*/}}
|
||||||
</span>
|
</span>
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<span class="clear"> <span class="block m-t-xs"> <strong class="font-bold">
|
<span class="clear"> <span class="block m-t-xs"> <strong class="font-bold">
|
||||||
|
@ -53,42 +53,42 @@
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "index" .menu}}active{{end}}">
|
<li class="{{if eq "index" .menu}}active{{end}}">
|
||||||
<a href="/"><i class="fa fa-dashboard"></i> <span langtag="menu-dashboard"
|
<a href="{{.web_base_url}}/"><i class="fa fa-dashboard"></i> <span langtag="menu-dashboard"
|
||||||
class="nav-label">仪表盘</span></a>
|
class="nav-label">仪表盘</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "client" .menu}}active{{end}}">
|
<li class="{{if eq "client" .menu}}active{{end}}">
|
||||||
<a href="/client/list"><i class="fa fa-clipboard"></i> <span langtag="menu-client"
|
<a href="{{.web_base_url}}/client/list"><i class="fa fa-clipboard"></i> <span langtag="menu-client"
|
||||||
class="nav-label">客户端</span></a>
|
class="nav-label">客户端</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "host" .menu}}active{{end}}">
|
<li class="{{if eq "host" .menu}}active{{end}}">
|
||||||
<a href="/index/hostlist"><i class="fa fa-paperclip"></i> <span langtag="menu-host"
|
<a href="{{.web_base_url}}/index/hostlist"><i class="fa fa-paperclip"></i> <span langtag="menu-host"
|
||||||
class="nav-label">域名解析</span></a>
|
class="nav-label">域名解析</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "tcp" .menu}}active{{end}}">
|
<li class="{{if eq "tcp" .menu}}active{{end}}">
|
||||||
<a href="/index/tcp"><i class="fa fa-line-chart"></i> <span langtag="menu-tcp"
|
<a href="{{.web_base_url}}/index/tcp"><i class="fa fa-line-chart"></i> <span langtag="menu-tcp"
|
||||||
class="nav-label">tcp隧道</span></a>
|
class="nav-label">tcp隧道</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "udp" .menu}}active{{end}}">
|
<li class="{{if eq "udp" .menu}}active{{end}}">
|
||||||
<a href="/index/udp"><i class="fa fa-server"></i> <span langtag="menu-udp"
|
<a href="{{.web_base_url}}/index/udp"><i class="fa fa-server"></i> <span langtag="menu-udp"
|
||||||
class="nav-label">udp隧道</span></a>
|
class="nav-label">udp隧道</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "http" .menu}}active{{end}}">
|
<li class="{{if eq "http" .menu}}active{{end}}">
|
||||||
<a href="/index/http"><i class="fa fa-html5"></i> <span langtag="menu-http"
|
<a href="{{.web_base_url}}/index/http"><i class="fa fa-html5"></i> <span langtag="menu-http"
|
||||||
class="nav-label">http代理</span></a>
|
class="nav-label">http代理</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "socks5" .menu}}active{{end}}">
|
<li class="{{if eq "socks5" .menu}}active{{end}}">
|
||||||
<a href="/index/socks5"><i class="fa fa-table"></i> <span langtag="menu-socks5" class="nav-label">socks5代理</span></a>
|
<a href="{{.web_base_url}}/index/socks5"><i class="fa fa-table"></i> <span langtag="menu-socks5" class="nav-label">socks5代理</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "secret" .menu}}active{{end}}">
|
<li class="{{if eq "secret" .menu}}active{{end}}">
|
||||||
<a href="/index/secret"><i class="fa fa-backward"></i> <span langtag="menu-secret"
|
<a href="{{.web_base_url}}/index/secret"><i class="fa fa-backward"></i> <span langtag="menu-secret"
|
||||||
class="nav-label">私密代理</span></a>
|
class="nav-label">私密代理</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "p2p" .menu}}active{{end}}">
|
<li class="{{if eq "p2p" .menu}}active{{end}}">
|
||||||
<a href="/index/p2p"><i class="fa fa-dashcube"></i> <span langtag="menu-p2p"
|
<a href="{{.web_base_url}}/index/p2p"><i class="fa fa-dashcube"></i> <span langtag="menu-p2p"
|
||||||
class="nav-label">p2p代理</span></a>
|
class="nav-label">p2p代理</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="{{if eq "file" .menu}}active{{end}}">
|
<li class="{{if eq "file" .menu}}active{{end}}">
|
||||||
<a href="/index/file"><i class="fa fa-laptop"></i> <span langtag="menu-file"
|
<a href="{{.web_base_url}}/index/file"><i class="fa fa-laptop"></i> <span langtag="menu-file"
|
||||||
class="nav-label">文件代理</span></a>
|
class="nav-label">文件代理</span></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/login/out">
|
<a href="{{.web_base_url}}/login/out">
|
||||||
<i class="fa fa-sign-out"></i> logout
|
<i class="fa fa-sign-out"></i> logout
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -142,6 +142,9 @@
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
window.nps = {
|
||||||
|
"web_base_url": {{.web_base_url}},
|
||||||
|
}
|
||||||
// googleTranslateElementInit()
|
// googleTranslateElementInit()
|
||||||
//
|
//
|
||||||
// function googleTranslateElementInit() {
|
// function googleTranslateElementInit() {
|
||||||
|
|
Loading…
Reference in New Issue