mirror of https://github.com/ehang-io/nps
Merge a58bec2efe
into ab648d6f0c
commit
130ad90029
|
@ -27,11 +27,15 @@ const (
|
|||
CONN_TCP = "tcp"
|
||||
CONN_UDP = "udp"
|
||||
CONN_TEST = "TST"
|
||||
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
WWW-Authenticate: Basic realm="easyProxy"
|
||||
UnauthorizedBytes = `HTTP/1.1 407 Proxy Authentication Required
|
||||
Server: Proxy
|
||||
Proxy-Authenticate: Basic realm="easyProxy Authentication"
|
||||
Connection: Close
|
||||
Proxy-Connection: Close
|
||||
Content-Length: 0
|
||||
|
||||
`
|
||||
|
||||
401 Unauthorized`
|
||||
ConnectionFailBytes = `HTTP/1.1 404 Not Found
|
||||
|
||||
`
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -49,8 +50,79 @@ func DomainCheck(domain string) bool {
|
|||
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
|
||||
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)
|
||||
if len(s) != 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 {
|
||||
return false
|
||||
}
|
||||
return pair[0] == user && pair[1] == passwd
|
||||
|
||||
return CheckAuthWithAccountMap(pair[0], pair[1], user, passwd, accountMap)
|
||||
}
|
||||
|
||||
//get bool by str
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"ehang.io/nps/bridge"
|
||||
|
@ -63,11 +64,13 @@ func (s *BaseServer) writeConnFail(c net.Conn) {
|
|||
}
|
||||
|
||||
//auth check
|
||||
func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string) error {
|
||||
if u != "" && p != "" && !common.CheckAuth(r, u, p) {
|
||||
c.Write([]byte(common.UnauthorizedBytes))
|
||||
func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string, AccountMap map[string]string) error {
|
||||
if !common.CheckAuth(r, u, p, AccountMap) {
|
||||
var resp = common.UnauthorizedBytes
|
||||
resp = strings.ReplaceAll(resp, "\n", "\r\n")
|
||||
c.Write([]byte(resp))
|
||||
c.Close()
|
||||
return errors.New("401 Unauthorized")
|
||||
return errors.New("407 Unauthorized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ reset:
|
|||
if !isReset {
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ func (https *HttpsServer) handleHttps(c net.Conn) {
|
|||
return
|
||||
}
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -302,7 +302,13 @@ func (s *Sock5ModeServer) handleConn(c net.Conn) {
|
|||
c.Close()
|
||||
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
|
||||
c.Write(buf)
|
||||
if err := s.Auth(c); err != nil {
|
||||
|
@ -340,21 +346,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error {
|
|||
return err
|
||||
}
|
||||
|
||||
var U, P string
|
||||
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 common.CheckAuthWithAccountMap(string(user), string(pass), s.task.Client.Cnf.U, s.task.Client.Cnf.P, s.task.MultiAccount.AccountMap) {
|
||||
if _, err := c.Write([]byte{userAuthVersion, authSuccess}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -40,8 +40,11 @@ func (s *TunnelModeServer) Start() error {
|
|||
return
|
||||
}
|
||||
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)
|
||||
s.task.Client.AddConn()
|
||||
err := s.process(conn.NewConn(c), s)
|
||||
if err == nil {
|
||||
s.task.Client.AddConn()
|
||||
}
|
||||
|
||||
}, &s.listener)
|
||||
}
|
||||
|
||||
|
@ -114,12 +117,14 @@ func ProcessHttp(c *conn.Conn, s *TunnelModeServer) error {
|
|||
logs.Info(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" {
|
||||
c.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
|
||||
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue