Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>

This commit is contained in:
arraykeys@gmail.com
2018-03-28 13:14:06 +08:00
parent d81d5ffe06
commit 4a34566f08
8 changed files with 206 additions and 110 deletions

View File

@ -1,4 +1,10 @@
proxy更新日志 proxy更新日志
v4.6
1.sps,http(s),socks5,内网穿透都做了大量的超时优化处理,更加稳定.
2.sps增加了强大的树形级联认证支持,可以轻松构建你的认证代理网络.
3.手册增加了6.6对sps认证功能的介绍.
v4.5 v4.5
1.优化了mux内网穿透连接管理逻辑,增强了稳定性. 1.优化了mux内网穿透连接管理逻辑,增强了稳定性.
2.mux内网穿透增加了tcp和kcp协议支持,之前是tls,现在支持三种协议tcp,tls,kcp. 2.mux内网穿透增加了tcp和kcp协议支持,之前是tls,现在支持三种协议tcp,tls,kcp.

View File

@ -127,7 +127,8 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- [6.3 SOCKS5转HTTP(S)+SOCKS5](#63-socks5转httpssocks5) - [6.3 SOCKS5转HTTP(S)+SOCKS5](#63-socks5转httpssocks5)
- [6.4 链式连接](#64-链式连接) - [6.4 链式连接](#64-链式连接)
- [6.5 监听多个端口](#65-监听多个端口) - [6.5 监听多个端口](#65-监听多个端口)
- [6.6 查看帮助](#66-查看帮助) - [6.6 认证功能](#66-认证功能)
- [6.7 查看帮助](#67-查看帮助)
- [7. KCP配置](#7kcp配置) - [7. KCP配置](#7kcp配置)
- [7.1 配置介绍](#71-配置介绍) - [7.1 配置介绍](#71-配置介绍)
- [7.2 详细配置](#72-详细配置) - [7.2 详细配置](#72-详细配置)
@ -736,7 +737,47 @@ vps023.3.3.3
一般情况下监听一个端口就可以不过如果作为反向代理需要同时监听80和443两个端口那么-p参数是支持的 一般情况下监听一个端口就可以不过如果作为反向代理需要同时监听80和443两个端口那么-p参数是支持的
格式是:`-p 0.0.0.0:80,0.0.0.0:443`,多个绑定用逗号分隔即可。 格式是:`-p 0.0.0.0:80,0.0.0.0:443`,多个绑定用逗号分隔即可。
#### **6.6 查看帮助** #### **6.6 认证功能**
sps支持http(s)\socks5代理认证,可以级联认证,有四个重要的信息:
1:用户发送认证信息`user-auth`
2:设置的本地认证信息`local-auth`
3:设置的连接上级使用的认证信息`parent-auth`
4:最终发送给上级的认证信息`auth-info-to-parent`
他们的情况关系如下:
| user-auth | local-auth | parent-auth | auth-info-to-parent
| 有/没有 | 有 | 有 | 来自parent-auth
| 有/没有 | 没有 | 有 | 来自parent-auth
| 有/没有 | 有 | 没有 | 无
| 没有 | 没有 | 没有 | 无
| 有 | 没有 | 没有 | 来自user-auth
对于sps代理我们可以进行用户名密码认证,认证的用户名和密码可以在命令行指定
`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -t tcp -p ":33080" -a "user1:pass1" -a "user2:pass2"`
多个用户,重复-a参数即可.
也可以放在文件中,格式是一行一个"用户名:密码",然后用-F指定.
`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -t tcp -p ":33080" -F auth-file.txt`
如果上级有认证,下级可以通过-A参数设置认证信息,比如:
上级:`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -t tcp -p ":33080" -a "user1:pass1" -a "user2:pass2"`
下级:`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -A "user1:pass1" -t tcp -p ":33080" `
另外,sps代理,本地认证集成了外部HTTP API认证,我们可以通过--auth-url参数指定一个http url接口地址,
然后有用户连接的时候,proxy会GET方式请求这url,带上下面四个参数,如果返回HTTP状态码204,代表认证成功
其它情况认为认证失败.
比如:
`./proxy sps -S http -T tcp -P 127.0.0.1:8080 -t tcp -p ":33080" --auth-url "http://test.com/auth.php"`
用户连接的时候,proxy会GET方式请求这url("http://test.com/auth.php"),
带上user,pass,ip,三个参数:
http://test.com/auth.php?user={USER}&pass={PASS}&ip={IP}&target={TARGET}
user:用户名
pass:密码
ip:用户的IP,比如:192.168.1.200
target:如果客户端是http(s)代理请求,这里代表的是请求的完整url,其它情况为空.
如果没有-a或-F或--auth-url参数,就是关闭本地认证.
如果没有-A参数,连接上级不使用认证.
#### **6.7 查看帮助**
`./proxy help sps` `./proxy help sps`
### **7.KCP配置** ### **7.KCP配置**

View File

@ -223,7 +223,14 @@ func initConfig() (err error) {
spsArgs.ParentServiceType = sps.Flag("parent-service-type", "parent service type <http|socks>").Short('S').Enum("http", "socks") spsArgs.ParentServiceType = sps.Flag("parent-service-type", "parent service type <http|socks>").Short('S').Enum("http", "socks")
spsArgs.DNSAddress = sps.Flag("dns-address", "if set this, proxy will use this dns for resolve doamin").Short('q').Default("").String() spsArgs.DNSAddress = sps.Flag("dns-address", "if set this, proxy will use this dns for resolve doamin").Short('q').Default("").String()
spsArgs.DNSTTL = sps.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int() spsArgs.DNSTTL = sps.Flag("dns-ttl", "caching seconds of dns query result").Short('e').Default("300").Int()
spsArgs.AuthFile = sps.Flag("auth-file", "http basic auth file,\"username:password\" each line in file").Short('F').String()
spsArgs.Auth = sps.Flag("auth", "socks auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings()
spsArgs.LocalIPS = sps.Flag("local bind ips", "if your host behind a nat,set your public ip here avoid dead loop").Short('g').Strings()
spsArgs.AuthURL = sps.Flag("auth-url", "auth username and password will send to this url,response http code equal to 'auth-code' means ok,others means fail.").Default("").String()
spsArgs.AuthURLTimeout = sps.Flag("auth-timeout", "access 'auth-url' timeout milliseconds").Default("3000").Int()
spsArgs.AuthURLOkCode = sps.Flag("auth-code", "access 'auth-url' success http code").Default("204").Int()
spsArgs.AuthURLRetry = sps.Flag("auth-retry", "access 'auth-url' fail and retry count").Default("0").Int()
spsArgs.ParentAuth = sps.Flag("parent-auth", "parent socks auth username and password, such as: -A user1:pass1").Short('A').String()
//parse args //parse args
serviceName := kingpin.MustParse(app.Parse(os.Args[1:])) serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))

View File

@ -215,6 +215,14 @@ type SPSArgs struct {
ParentServiceType *string ParentServiceType *string
DNSAddress *string DNSAddress *string
DNSTTL *int DNSTTL *int
AuthFile *string
Auth *[]string
AuthURL *string
AuthURLOkCode *int
AuthURLTimeout *int
AuthURLRetry *int
LocalIPS *[]string
ParentAuth *string
} }
func (a *SPSArgs) Protocol() string { func (a *SPSArgs) Protocol() string {

View File

@ -2,6 +2,7 @@ package services
import ( import (
"bytes" "bytes"
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -12,18 +13,21 @@ import (
"snail007/proxy/utils/socks" "snail007/proxy/utils/socks"
"strconv" "strconv"
"strings" "strings"
"time"
) )
type SPS struct { type SPS struct {
outPool utils.OutPool outPool utils.OutPool
cfg SPSArgs cfg SPSArgs
domainResolver utils.DomainResolver domainResolver utils.DomainResolver
basicAuth utils.BasicAuth
} }
func NewSPS() Service { func NewSPS() Service {
return &SPS{ return &SPS{
outPool: utils.OutPool{}, outPool: utils.OutPool{},
cfg: SPSArgs{}, cfg: SPSArgs{},
basicAuth: utils.BasicAuth{},
} }
} }
func (s *SPS) CheckArgs() { func (s *SPS) CheckArgs() {
@ -46,6 +50,10 @@ func (s *SPS) CheckArgs() {
} }
func (s *SPS) InitService() { func (s *SPS) InitService() {
s.InitOutConnPool() s.InitOutConnPool()
if *s.cfg.DNSAddress != "" {
(*s).domainResolver = utils.NewDomainResolver(*s.cfg.DNSAddress, *s.cfg.DNSTTL)
}
s.InitBasicAuth()
} }
func (s *SPS) InitOutConnPool() { func (s *SPS) InitOutConnPool() {
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP { if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP || *s.cfg.ParentType == TYPE_KCP {
@ -117,7 +125,7 @@ func (s *SPS) callback(inConn net.Conn) {
err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType) err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType)
} }
if err != nil { if err != nil {
log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err) log.Printf("connect to %s parent %s fail, ERR:%s from %s", *s.cfg.ParentType, *s.cfg.Parent, err, inConn.RemoteAddr())
utils.CloseConn(&inConn) utils.CloseConn(&inConn)
} }
} }
@ -131,51 +139,32 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
return return
} }
address := "" address := ""
var auth socks.Auth
var forwardBytes []byte var forwardBytes []byte
//fmt.Printf("%v", header) //fmt.Printf("%v", header)
if header[0] == socks.VERSION_V5 { if header[0] == socks.VERSION_V5 {
//socks //socks5 server
methodReq, e := socks.NewMethodsRequest(*inConn, header) var serverConn *socks.ServerConn
if e != nil { if s.IsBasicAuth() {
log.Printf("new method request err:%s", e) serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), &s.basicAuth, "", header)
utils.CloseConn(inConn) } else {
err = e.(error) serverConn = socks.NewServerConn(inConn, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, "", header)
}
if err = serverConn.Handshake(); err != nil {
return return
} }
if !methodReq.Select(socks.Method_NO_AUTH) { address = serverConn.Target()
methodReq.Reply(socks.Method_NONE_ACCEPTABLE) auth = serverConn.AuthData()
utils.CloseConn(inConn)
log.Printf("none method found : Method_NO_AUTH")
return
}
//method select reply
err = methodReq.Reply(socks.Method_NO_AUTH)
if err != nil {
log.Printf("reply answer data fail,ERR: %s", err)
utils.CloseConn(inConn)
return
}
//request detail
request, e := socks.NewRequest(*inConn)
if e != nil {
log.Printf("read request data fail,ERR: %s", e)
utils.CloseConn(inConn)
err = e.(error)
return
}
if request.CMD() != socks.CMD_CONNECT {
//只支持tcp
request.TCPReply(socks.REP_UNKNOWN)
utils.CloseConn(inConn)
err = errors.New("cmd not supported")
return
}
address = request.Addr()
request.TCPReply(socks.REP_SUCCESS)
} else if bytes.IndexByte(header, '\n') != -1 { } else if bytes.IndexByte(header, '\n') != -1 {
//http //http
var request utils.HTTPRequest var request utils.HTTPRequest
request, err = utils.NewHTTPRequest(inConn, 1024, false, nil, header) (*inConn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
if s.IsBasicAuth() {
request, err = utils.NewHTTPRequest(inConn, 1024, true, &s.basicAuth, header)
} else {
request, err = utils.NewHTTPRequest(inConn, 1024, false, nil, header)
}
(*inConn).SetDeadline(time.Time{})
if err != nil { if err != nil {
log.Printf("new http request fail,ERR: %s", err) log.Printf("new http request fail,ERR: %s", err)
utils.CloseConn(inConn) utils.CloseConn(inConn)
@ -189,6 +178,17 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
forwardBytes = request.HeadBuf forwardBytes = request.HeadBuf
} }
address = request.Host address = request.Host
var userpass string
if s.IsBasicAuth() {
userpass, err = request.GetAuthDataStr()
if err != nil {
return
}
userpassA := strings.Split(userpass, ":")
if len(userpassA) == 2 {
auth = socks.Auth{User: userpassA[0], Password: userpassA[1]}
}
}
} else { } else {
log.Printf("unknown request from: %s,%s", (*inConn).RemoteAddr(), string(header)) log.Printf("unknown request from: %s,%s", (*inConn).RemoteAddr(), string(header))
utils.CloseConn(inConn) utils.CloseConn(inConn)
@ -207,12 +207,42 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
utils.CloseConn(inConn) utils.CloseConn(inConn)
return return
} }
//ask parent for connect to target address //ask parent for connect to target address
if *s.cfg.ParentServiceType == "http" { if *s.cfg.ParentServiceType == "http" {
//http parent //http parent
fmt.Fprintf(outConn, "CONNECT %s HTTP/1.1\r\n", address) pb := new(bytes.Buffer)
pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\nProxy-Connection: Keep-Alive\r\n", address)))
//Proxy-Authorization:\r\n
u := ""
if *s.cfg.ParentAuth != "" {
a := strings.Split(*s.cfg.ParentAuth, ":")
if len(a) != 2 {
err = fmt.Errorf("parent auth data format error")
return
}
u = fmt.Sprintf("%s:%s", a[0], a[1])
} else {
if !s.IsBasicAuth() && auth.Password != "" && auth.User != "" {
u = fmt.Sprintf("%s:%s", auth.User, auth.Password)
}
}
if u != "" {
pb.Write([]byte(fmt.Sprintf("Proxy-Authorization:Basic %s\r\n", base64.StdEncoding.EncodeToString([]byte(u)))))
}
outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = outConn.Write(pb.Bytes())
outConn.SetDeadline(time.Time{})
if err != nil {
log.Printf("write CONNECT to %s , err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
return
}
reply := make([]byte, 100) reply := make([]byte, 100)
n, err = outConn.Read(reply) outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = outConn.Read(reply)
outConn.SetDeadline(time.Time{})
if err != nil { if err != nil {
log.Printf("read reply from %s , err:%s", *s.cfg.Parent, err) log.Printf("read reply from %s , err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn) utils.CloseConn(inConn)
@ -222,53 +252,25 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
//log.Printf("reply: %s", string(reply[:n])) //log.Printf("reply: %s", string(reply[:n]))
} else { } else {
log.Printf("connect %s", address) log.Printf("connect %s", address)
//socks parent //socks client
//send auth type var clientConn *socks.ClientConn
_, err = outConn.Write([]byte{0x05, 0x01, 0x00}) if *s.cfg.ParentAuth != "" {
if err != nil { a := strings.Split(*s.cfg.ParentAuth, ":")
log.Printf("write method to %s fail, err:%s", *s.cfg.Parent, err) if len(a) != 2 {
utils.CloseConn(inConn) err = fmt.Errorf("parent auth data format error")
utils.CloseConn(&outConn) return
}
clientConn = socks.NewClientConn(&outConn, "tcp", address, time.Millisecond*time.Duration(*s.cfg.Timeout), &socks.Auth{User: a[0], Password: a[1]}, header)
} else {
if !s.IsBasicAuth() && auth.Password != "" && auth.User != "" {
clientConn = socks.NewClientConn(&outConn, "tcp", address, time.Millisecond*time.Duration(*s.cfg.Timeout), &auth, header)
} else {
clientConn = socks.NewClientConn(&outConn, "tcp", address, time.Millisecond*time.Duration(*s.cfg.Timeout), nil, header)
}
}
if err = clientConn.Handshake(); err != nil {
return return
} }
//read reply
reply := make([]byte, 512)
n, err = outConn.Read(reply)
if err != nil {
log.Printf("read reply from %s , err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
return
}
//log.Printf("method reply %v", reply[:n])
//build request
buf, err = s.buildRequest(address)
if err != nil {
log.Printf("build request to %s fail , err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
return
}
//send address request
_, err = outConn.Write(buf)
if err != nil {
log.Printf("write request to %s fail, err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
return
}
//read reply
reply = make([]byte, 512)
n, err = outConn.Read(reply)
if err != nil {
log.Printf("read reply from %s , err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
return
}
//log.Printf("request reply %v", reply[:n])
} }
//forward client data to target,if necessary. //forward client data to target,if necessary.
if len(forwardBytes) > 0 { if len(forwardBytes) > 0 {
@ -283,6 +285,34 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
log.Printf("conn %s - %s connected", inAddr, outAddr) log.Printf("conn %s - %s connected", inAddr, outAddr)
return return
} }
func (s *SPS) InitBasicAuth() (err error) {
if *s.cfg.DNSAddress != "" {
s.basicAuth = utils.NewBasicAuth(&(*s).domainResolver)
} else {
s.basicAuth = utils.NewBasicAuth(nil)
}
if *s.cfg.AuthURL != "" {
s.basicAuth.SetAuthURL(*s.cfg.AuthURL, *s.cfg.AuthURLOkCode, *s.cfg.AuthURLTimeout, *s.cfg.AuthURLRetry)
log.Printf("auth from %s", *s.cfg.AuthURL)
}
if *s.cfg.AuthFile != "" {
var n = 0
n, err = s.basicAuth.AddFromFile(*s.cfg.AuthFile)
if err != nil {
err = fmt.Errorf("auth-file ERR:%s", err)
return
}
log.Printf("auth data added from file %d , total:%d", n, s.basicAuth.Total())
}
if len(*s.cfg.Auth) > 0 {
n := s.basicAuth.Add(*s.cfg.Auth)
log.Printf("auth data added %d, total:%d", n, s.basicAuth.Total())
}
return
}
func (s *SPS) IsBasicAuth() bool {
return *s.cfg.AuthFile != "" || len(*s.cfg.Auth) > 0 || *s.cfg.AuthURL != ""
}
func (s *SPS) buildRequest(address string) (buf []byte, err error) { func (s *SPS) buildRequest(address string) (buf []byte, err error) {
host, portStr, err := net.SplitHostPort(address) host, portStr, err := net.SplitHostPort(address)
if err != nil { if err != nil {

View File

@ -63,7 +63,7 @@ func NewClientConn(conn *net.Conn, network, target string, timeout time.Duration
// connect takes an existing connection to a socks5 proxy server, // connect takes an existing connection to a socks5 proxy server,
// and commands the server to extend that connection to target, // and commands the server to extend that connection to target,
// which must be a canonical address with a host and port. // which must be a canonical address with a host and port.
func (s *ClientConn) Connect() error { func (s *ClientConn) Handshake() error {
host, portStr, err := net.SplitHostPort(s.addr) host, portStr, err := net.SplitHostPort(s.addr)
if err != nil { if err != nil {
return err return err

View File

@ -106,14 +106,15 @@ func (s *ServerConn) Handshake() (err error) {
err = fmt.Errorf("new methods request fail,ERR: %s", e) err = fmt.Errorf("new methods request fail,ERR: %s", e)
return return
} }
if s.auth == nil { //log.Printf("%v,s.auth == %v && methodReq.Select(Method_NO_AUTH) %v", methodReq.methods, s.auth, methodReq.Select(Method_NO_AUTH))
if !methodReq.Select(Method_NO_AUTH) { if s.auth == nil && methodReq.Select(Method_NO_AUTH) && !methodReq.Select(Method_USER_PASS) {
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout)) // if !methodReq.Select(Method_NO_AUTH) {
methodReq.Reply(Method_NONE_ACCEPTABLE) // (*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
(*s.conn).SetReadDeadline(time.Time{}) // methodReq.Reply(Method_NONE_ACCEPTABLE)
err = fmt.Errorf("none method found : Method_NO_AUTH") // (*s.conn).SetReadDeadline(time.Time{})
return // err = fmt.Errorf("none method found : Method_NO_AUTH")
} // return
// }
s.method = Method_NO_AUTH s.method = Method_NO_AUTH
//method select reply //method select reply
(*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout)) (*s.conn).SetReadDeadline(time.Now().Add(time.Second * s.timeout))
@ -158,7 +159,7 @@ func (s *ServerConn) Handshake() (err error) {
//err = fmt.Errorf("user:%s,pass:%s", user, pass) //err = fmt.Errorf("user:%s,pass:%s", user, pass)
//auth //auth
_addr := strings.Split(remoteAddr.String(), ":") _addr := strings.Split(remoteAddr.String(), ":")
if s.auth.CheckUserPass(s.user, s.password, _addr[0], "") { if s.auth == nil || s.auth.CheckUserPass(s.user, s.password, _addr[0], "") {
(*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout))) (*s.conn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(s.timeout)))
_, err = (*s.conn).Write([]byte{0x01, 0x00}) _, err = (*s.conn).Write([]byte{0x01, 0x00})
(*s.conn).SetDeadline(time.Time{}) (*s.conn).SetDeadline(time.Time{})

View File

@ -317,7 +317,7 @@ func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *
req = HTTPRequest{ req = HTTPRequest{
conn: inConn, conn: inConn,
} }
if len(header) == 1 { if header != nil && len(header) == 1 && len(header[0]) > 1 {
buf = header[0] buf = header[0]
n = len(header[0]) n = len(header[0])
} else { } else {
@ -402,18 +402,13 @@ func (req *HTTPRequest) IsHTTPS() bool {
return req.Method == "CONNECT" return req.Method == "CONNECT"
} }
func (req *HTTPRequest) BasicAuth() (err error) { func (req *HTTPRequest) GetAuthDataStr() (basicInfo string, err error) {
// log.Printf("request :%s", string(req.HeadBuf)) // log.Printf("request :%s", string(req.HeadBuf))
code := "407"
authorization := req.getHeader("Proxy-Authorization") authorization := req.getHeader("Proxy-Authorization")
// if authorization == "" {
// authorization = req.getHeader("Authorization")
// code = "401"
// }
authorization = strings.Trim(authorization, " \r\n\t") authorization = strings.Trim(authorization, " \r\n\t")
if authorization == "" { if authorization == "" {
fmt.Fprintf((*req.conn), "HTTP/1.1 %s Unauthorized\r\nWWW-Authenticate: Basic realm=\"\"\r\n\r\nUnauthorized", code) fmt.Fprintf((*req.conn), "HTTP/1.1 %s Unauthorized\r\nWWW-Authenticate: Basic realm=\"\"\r\n\r\nUnauthorized", "407")
CloseConn(req.conn) CloseConn(req.conn)
err = errors.New("require auth header data") err = errors.New("require auth header data")
return return
@ -431,6 +426,10 @@ func (req *HTTPRequest) BasicAuth() (err error) {
CloseConn(req.conn) CloseConn(req.conn)
return return
} }
basicInfo = string(user)
return
}
func (req *HTTPRequest) BasicAuth() (err error) {
addr := strings.Split((*req.conn).RemoteAddr().String(), ":") addr := strings.Split((*req.conn).RemoteAddr().String(), ":")
URL := "" URL := ""
if req.IsHTTPS() { if req.IsHTTPS() {
@ -438,10 +437,14 @@ func (req *HTTPRequest) BasicAuth() (err error) {
} else { } else {
URL = req.getHTTPURL() URL = req.getHTTPURL()
} }
user, err := req.GetAuthDataStr()
if err != nil {
return
}
authOk := (*req.basicAuth).Check(string(user), addr[0], URL) authOk := (*req.basicAuth).Check(string(user), addr[0], URL)
//log.Printf("auth %s,%v", string(user), authOk) //log.Printf("auth %s,%v", string(user), authOk)
if !authOk { if !authOk {
fmt.Fprintf((*req.conn), "HTTP/1.1 %s Unauthorized\r\n\r\nUnauthorized", code) fmt.Fprintf((*req.conn), "HTTP/1.1 %s Unauthorized\r\n\r\nUnauthorized", "407")
CloseConn(req.conn) CloseConn(req.conn)
err = fmt.Errorf("basic auth fail") err = fmt.Errorf("basic auth fail")
return return