pull/968/merge
Immortal 2022-01-02 16:56:13 +00:00 committed by GitHub
commit 130ad90029
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 33 deletions

View File

@ -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
`

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}