mirror of https://github.com/ehang-io/nps
Merge a58bec2efe
into ab648d6f0c
commit
130ad90029
|
@ -27,11 +27,15 @@ const (
|
||||||
CONN_TCP = "tcp"
|
CONN_TCP = "tcp"
|
||||||
CONN_UDP = "udp"
|
CONN_UDP = "udp"
|
||||||
CONN_TEST = "TST"
|
CONN_TEST = "TST"
|
||||||
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
|
UnauthorizedBytes = `HTTP/1.1 407 Proxy Authentication Required
|
||||||
Content-Type: text/plain; charset=utf-8
|
Server: Proxy
|
||||||
WWW-Authenticate: Basic realm="easyProxy"
|
Proxy-Authenticate: Basic realm="easyProxy Authentication"
|
||||||
|
Connection: Close
|
||||||
|
Proxy-Connection: Close
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
401 Unauthorized`
|
|
||||||
ConnectionFailBytes = `HTTP/1.1 404 Not Found
|
ConnectionFailBytes = `HTTP/1.1 404 Not Found
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/astaxie/beego/logs"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -49,8 +50,79 @@ func DomainCheck(domain string) bool {
|
||||||
return match
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断是否有有效的账号
|
||||||
|
func hasValidAccount(accountMap map[string]string) bool {
|
||||||
|
if accountMap == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for u, p := range accountMap {
|
||||||
|
if u != "" && p != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否需要验证
|
||||||
|
// user global user
|
||||||
|
// passwd global passwd
|
||||||
|
// accountMap enable multi user auth
|
||||||
|
func HasValid(user, passwd string, accountMap map[string]string) bool {
|
||||||
|
return hasValidAccount(accountMap) || (user != "" && passwd != "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckAuthWithAccountMap
|
||||||
|
// u current login user
|
||||||
|
// p current login passwd
|
||||||
|
// user global user
|
||||||
|
// passwd global passwd
|
||||||
|
// accountMap enable multi user auth
|
||||||
|
func checkAuthWithAccountMap(u, p, user, passwd string, accountMap map[string]string) bool {
|
||||||
|
// 是否需要验证
|
||||||
|
if !HasValid(user, passwd, accountMap) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalid user or passwd
|
||||||
|
if u == "" || p == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// global user auth
|
||||||
|
if u == user && p == passwd {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi user auth
|
||||||
|
if accountMap == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return accountMap[u] == p
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckAuthWithAccountMap
|
||||||
|
// u current login user
|
||||||
|
// p current login passwd
|
||||||
|
// user global user
|
||||||
|
// passwd global passwd
|
||||||
|
// accountMap enable multi user auth
|
||||||
|
func CheckAuthWithAccountMap(u, p, user, passwd string, accountMap map[string]string) bool {
|
||||||
|
isValid := checkAuthWithAccountMap(u, p, user, passwd, accountMap)
|
||||||
|
if !isValid {
|
||||||
|
logs.Info("账号验证失败")
|
||||||
|
}
|
||||||
|
return isValid
|
||||||
|
}
|
||||||
|
|
||||||
//Check if the Request request is validated
|
//Check if the Request request is validated
|
||||||
func CheckAuth(r *http.Request, user, passwd string) bool {
|
func CheckAuth(r *http.Request, user, passwd string, accountMap map[string]string) bool {
|
||||||
|
// 是否需要验证
|
||||||
|
if !HasValid(user, passwd, accountMap) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
|
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
|
||||||
if len(s) != 2 {
|
if len(s) != 2 {
|
||||||
s = strings.SplitN(r.Header.Get("Proxy-Authorization"), " ", 2)
|
s = strings.SplitN(r.Header.Get("Proxy-Authorization"), " ", 2)
|
||||||
|
@ -68,7 +140,8 @@ func CheckAuth(r *http.Request, user, passwd string) bool {
|
||||||
if len(pair) != 2 {
|
if len(pair) != 2 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return pair[0] == user && pair[1] == passwd
|
|
||||||
|
return CheckAuthWithAccountMap(pair[0], pair[1], user, passwd, accountMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
//get bool by str
|
//get bool by str
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"ehang.io/nps/bridge"
|
"ehang.io/nps/bridge"
|
||||||
|
@ -63,11 +64,13 @@ func (s *BaseServer) writeConnFail(c net.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//auth check
|
//auth check
|
||||||
func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string) error {
|
func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string, AccountMap map[string]string) error {
|
||||||
if u != "" && p != "" && !common.CheckAuth(r, u, p) {
|
if !common.CheckAuth(r, u, p, AccountMap) {
|
||||||
c.Write([]byte(common.UnauthorizedBytes))
|
var resp = common.UnauthorizedBytes
|
||||||
|
resp = strings.ReplaceAll(resp, "\n", "\r\n")
|
||||||
|
c.Write([]byte(resp))
|
||||||
c.Close()
|
c.Close()
|
||||||
return errors.New("401 Unauthorized")
|
return errors.New("407 Unauthorized")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ reset:
|
||||||
if !isReset {
|
if !isReset {
|
||||||
defer host.Client.AddConn()
|
defer host.Client.AddConn()
|
||||||
}
|
}
|
||||||
if err = s.auth(r, c, host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
|
if err = s.auth(r, c, host.Client.Cnf.U, host.Client.Cnf.P, s.task.MultiAccount.AccountMap); err != nil {
|
||||||
logs.Warn("auth error", err, r.RemoteAddr)
|
logs.Warn("auth error", err, r.RemoteAddr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ func (https *HttpsServer) handleHttps(c net.Conn) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer host.Client.AddConn()
|
defer host.Client.AddConn()
|
||||||
if err = https.auth(r, conn.NewConn(c), host.Client.Cnf.U, host.Client.Cnf.P); err != nil {
|
if err = https.auth(r, conn.NewConn(c), host.Client.Cnf.U, host.Client.Cnf.P, https.task.MultiAccount.AccountMap); err != nil {
|
||||||
logs.Warn("auth error", err, r.RemoteAddr)
|
logs.Warn("auth error", err, r.RemoteAddr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,7 +302,13 @@ func (s *Sock5ModeServer) handleConn(c net.Conn) {
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (s.task.Client.Cnf.U != "" && s.task.Client.Cnf.P != "") || (s.task.MultiAccount != nil && len(s.task.MultiAccount.AccountMap) > 0) {
|
|
||||||
|
var accountMap map[string]string = nil
|
||||||
|
if s.task.MultiAccount != nil {
|
||||||
|
accountMap = s.task.MultiAccount.AccountMap
|
||||||
|
}
|
||||||
|
|
||||||
|
if common.HasValid(s.task.Client.Cnf.U, s.task.Client.Cnf.P, accountMap) {
|
||||||
buf[1] = UserPassAuth
|
buf[1] = UserPassAuth
|
||||||
c.Write(buf)
|
c.Write(buf)
|
||||||
if err := s.Auth(c); err != nil {
|
if err := s.Auth(c); err != nil {
|
||||||
|
@ -340,21 +346,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var U, P string
|
if common.CheckAuthWithAccountMap(string(user), string(pass), s.task.Client.Cnf.U, s.task.Client.Cnf.P, s.task.MultiAccount.AccountMap) {
|
||||||
if s.task.MultiAccount != nil {
|
|
||||||
// enable multi user auth
|
|
||||||
U = string(user)
|
|
||||||
var ok bool
|
|
||||||
P, ok = s.task.MultiAccount.AccountMap[U]
|
|
||||||
if !ok {
|
|
||||||
return errors.New("验证不通过")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
U = s.task.Client.Cnf.U
|
|
||||||
P = s.task.Client.Cnf.P
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(user) == U && string(pass) == P {
|
|
||||||
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
|
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,11 @@ func (s *TunnelModeServer) Start() error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logs.Trace("new tcp connection,local port %d,client %d,remote address %s", s.task.Port, s.task.Client.Id, c.RemoteAddr())
|
logs.Trace("new tcp connection,local port %d,client %d,remote address %s", s.task.Port, s.task.Client.Id, c.RemoteAddr())
|
||||||
s.process(conn.NewConn(c), s)
|
err := s.process(conn.NewConn(c), s)
|
||||||
s.task.Client.AddConn()
|
if err == nil {
|
||||||
|
s.task.Client.AddConn()
|
||||||
|
}
|
||||||
|
|
||||||
}, &s.listener)
|
}, &s.listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,12 +117,14 @@ func ProcessHttp(c *conn.Conn, s *TunnelModeServer) error {
|
||||||
logs.Info(err)
|
logs.Info(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.auth(r, c, s.task.Client.Cnf.U, s.task.Client.Cnf.P, s.task.MultiAccount.AccountMap); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if r.Method == "CONNECT" {
|
if r.Method == "CONNECT" {
|
||||||
c.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
|
c.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
|
||||||
rb = nil
|
rb = nil
|
||||||
}
|
}
|
||||||
if err := s.auth(r, c, s.task.Client.Cnf.U, s.task.Client.Cnf.P); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return s.DealClient(c, s.task.Client, addr, rb, common.CONN_TCP, nil, s.task.Flow, s.task.Target.LocalProxy)
|
return s.DealClient(c, s.task.Client, addr, rb, common.CONN_TCP, nil, s.task.Flow, s.task.Target.LocalProxy)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue