fix proxy auth
This commit is contained in:
parent
6b8d16042e
commit
419d9d886d
17
README.md
17
README.md
@ -4,7 +4,7 @@ gost - GO Simple Tunnel
|
||||
### GO语言实现的安全隧道
|
||||
|
||||
#### 特性
|
||||
1. 支持设置上层代理(客户端,服务器端均可)。
|
||||
1. 支持设置上层代理(客户端,服务器端均可),支持上层代理认证。
|
||||
2. 客户端可用作http(s), socks5代理。
|
||||
3. 服务器端兼容标准的socks5协议, 可直接用作socks5代理, 并额外增加协商加密功能。
|
||||
4. Tunnel UDP over TCP, UDP数据包使用TCP通道传输,以解决防火墙的限制。
|
||||
@ -16,15 +16,19 @@ gost - GO Simple Tunnel
|
||||
Google讨论组: https://groups.google.com/d/forum/go-gost
|
||||
|
||||
#### 版本更新
|
||||
##### v1.7
|
||||
* 支持认证功能,当作为http(s)代理时使用Basic Auth认证方式,当作为标准socks5代理时使用Username/Password认证方式
|
||||
###### Bug fix:
|
||||
* 修正当作为http代理时,POST请求出错问题
|
||||
|
||||
##### v1.6
|
||||
* 增加tls-auth加密方式,此方式必须设置认证密码(-p参数),原tls加密方式与v1.3版以前兼容
|
||||
|
||||
###### Bug fix:
|
||||
* 修正当不设置上层代理时,连接出错问题
|
||||
|
||||
##### v1.5
|
||||
* 支持设置上层socks5代理(注: http tunnel不支持)
|
||||
* 支持上层代理用户名密码验证
|
||||
* 支持上层代理认证
|
||||
|
||||
##### V1.4
|
||||
* 支持http tunnel(-http参数),使用http协议来传输数据(注: 效率低,非特殊情况下,不推荐使用)。
|
||||
@ -73,6 +77,13 @@ Google讨论组: https://groups.google.com/d/forum/go-gost
|
||||
* 客户端: `gost -L=:8899 -S=server_ip:8080`
|
||||
* 服务器: `gost -L=:8080`
|
||||
|
||||
##### 设置认证信息
|
||||
* 客户端: `gost -L=admin:123456@:8899 -S=server_ip:8080`
|
||||
* 服务器: `gost -L=admin:123456@:8080`
|
||||
|
||||
注:当服务器端设置了认证,默认的无加密模式(-m为空)不可用,
|
||||
即客户端或者使用认证方式(标准socks5模式),或者设置加密方式(gost兼容模式)。
|
||||
|
||||
##### 设置加密
|
||||
* 客户端: `gost -L=:8899 -S=server_ip:8080 -m=rc4-md5 -p=123456`
|
||||
* 服务器: `gost -L=:8080 -m=rc4-md5 -p=123456`
|
||||
|
70
client.go
70
client.go
@ -4,6 +4,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -162,21 +163,8 @@ func cliHandle(conn net.Conn) {
|
||||
handleSocks5(conn, methods)
|
||||
return
|
||||
}
|
||||
log.Println(string(b[:n]))
|
||||
for {
|
||||
if bytes.HasSuffix(b[:n], []byte("\r\n\r\n")) {
|
||||
break
|
||||
}
|
||||
|
||||
nn, err := conn.Read(b[n:])
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
n += nn
|
||||
}
|
||||
|
||||
req, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(b[:n])))
|
||||
req, err := http.ReadRequest(bufio.NewReader(newReqReader(b[:n], conn)))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
@ -202,7 +190,7 @@ func selectMethod(conn net.Conn, methods ...uint8) error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println(m)
|
||||
//log.Println(m)
|
||||
|
||||
switch m {
|
||||
case gosocks5.MethodUserPass:
|
||||
@ -333,20 +321,42 @@ func cliTunnelUDP(uconn *net.UDPConn, sconn net.Conn) {
|
||||
}
|
||||
|
||||
func clientHttpAuth(req *http.Request, conn net.Conn, username, password string) error {
|
||||
u, p, ok := req.BasicAuth()
|
||||
u, p, ok := proxyBasicAuth(req.Header.Get("Proxy-Authorization"))
|
||||
req.Header.Del("Proxy-Authorization")
|
||||
if !ok ||
|
||||
(len(username) > 0 && u != username) ||
|
||||
(len(password) > 0 && p != password) {
|
||||
conn.Write([]byte("HTTP/1.1 401 Not Authorized\r\n" +
|
||||
"WWW-Authenticate: Basic realm=\"Authorization Required\"\r\n" +
|
||||
conn.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\n" +
|
||||
"Proxy-Authenticate: Basic realm=\"gost\"\r\n" +
|
||||
"Proxy-Agent: gost/" + Version + "\r\n\r\n"))
|
||||
|
||||
return errors.New("Not Authorized")
|
||||
return errors.New("Proxy Authentication Required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func proxyBasicAuth(auth string) (username, password string, ok bool) {
|
||||
if auth == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(auth, "Basic ") {
|
||||
return
|
||||
}
|
||||
c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cs := string(c)
|
||||
s := strings.IndexByte(cs, ':')
|
||||
if s < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
return cs[:s], cs[s+1:], true
|
||||
}
|
||||
|
||||
func handleHttp(req *http.Request, conn net.Conn) {
|
||||
var host string
|
||||
var port uint16
|
||||
@ -523,3 +533,25 @@ func getShadowRequest(conn net.Conn) (addr *gosocks5.Addr, extra []byte, err err
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type reqReader struct {
|
||||
b []byte
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func newReqReader(b []byte, r io.Reader) *reqReader {
|
||||
return &reqReader{
|
||||
b: b,
|
||||
r: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *reqReader) Read(p []byte) (n int, err error) {
|
||||
if len(r.b) == 0 {
|
||||
return r.r.Read(p)
|
||||
}
|
||||
n = copy(p, r.b)
|
||||
r.b = r.b[n:]
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ func (s *Socks5Server) ListenAndServe() error {
|
||||
}
|
||||
|
||||
func serverSelectMethod(methods ...uint8) uint8 {
|
||||
log.Println(methods)
|
||||
//log.Println(methods)
|
||||
m := gosocks5.MethodNoAuth
|
||||
|
||||
for _, method := range methods {
|
||||
@ -116,7 +116,7 @@ func serverSelectMethod(methods ...uint8) uint8 {
|
||||
}
|
||||
|
||||
func serverMethodSelected(method uint8, conn net.Conn) (net.Conn, error) {
|
||||
log.Println(method)
|
||||
//log.Println(method)
|
||||
switch method {
|
||||
case gosocks5.MethodUserPass:
|
||||
var username, password string
|
||||
|
Loading…
Reference in New Issue
Block a user