merge with ginuerzh/gost master

This commit is contained in:
xiaoli 2017-11-22 21:19:41 +08:00
commit f9ebac8a69
4 changed files with 80 additions and 22 deletions

View File

@ -17,13 +17,16 @@ import (
"strings" "strings"
"time" "time"
"github.com/ginuerzh/gost"
"github.com/go-log/log" "github.com/go-log/log"
"github.com/go-redis/redis"
"github.com/jinzhu/configor"
"github.com/ginuerzh/gost"
) )
var ( var (
options route options route
routes []route routes []route
redisClient *redis.Client
) )
func init() { func init() {
@ -322,6 +325,10 @@ func (r *route) serve() error {
if node.User != nil { if node.User != nil {
users = append(users, node.User) users = append(users, node.User)
} }
redisClient, err := parseRedisUsersAuth(node.Values.Get("redis"))
if err != nil {
return err
}
certFile, keyFile := node.Values.Get("cert"), node.Values.Get("key") certFile, keyFile := node.Values.Get("cert"), node.Values.Get("key")
tlsCfg, err := tlsConfig(certFile, keyFile) tlsCfg, err := tlsConfig(certFile, keyFile)
if err != nil && certFile != "" && keyFile != "" { if err != nil && certFile != "" && keyFile != "" {
@ -436,6 +443,7 @@ func (r *route) serve() error {
gost.TLSConfigHandlerOption(tlsCfg), gost.TLSConfigHandlerOption(tlsCfg),
gost.WhitelistHandlerOption(whitelist), gost.WhitelistHandlerOption(whitelist),
gost.BlacklistHandlerOption(blacklist), gost.BlacklistHandlerOption(blacklist),
gost.RedisClientHandlerOption(redisClient),
) )
var handler gost.Handler var handler gost.Handler
switch node.Protocol { switch node.Protocol {
@ -603,7 +611,32 @@ func parseUsers(authFile string) (users []*url.Userinfo, err error) {
return return
} }
func parseIP(s string, port string) (ips []string) { func parseRedisUsersAuth(configFile string) (client *redis.Client, err error) {
if configFile == "" {
return
}
var Config = struct {
RedisServer struct {
Address string `default:"localhost:6379"`
Password string `default:""`
DB int `default:0`
}
}{}
configor.Load(&Config, configFile)
client = redis.NewClient(&redis.Options{
Addr: Config.RedisServer.Address,
Password: Config.RedisServer.Password,
DB: Config.RedisServer.DB,
})
_, err = client.Ping().Result()
return
}
func parseIP(s string) (ips []string) {
if s == "" { if s == "" {
return return
} }

5
cmd/gost/redis.yml Normal file
View File

@ -0,0 +1,5 @@
redisserver:
address: localhost:6379
password:
db:

View File

@ -9,6 +9,7 @@ import (
"github.com/ginuerzh/gosocks4" "github.com/ginuerzh/gosocks4"
"github.com/ginuerzh/gosocks5" "github.com/ginuerzh/gosocks5"
"github.com/go-log/log" "github.com/go-log/log"
"github.com/go-redis/redis"
) )
// Handler is a proxy server handler // Handler is a proxy server handler
@ -18,12 +19,13 @@ type Handler interface {
// HandlerOptions describes the options for Handler. // HandlerOptions describes the options for Handler.
type HandlerOptions struct { type HandlerOptions struct {
Addr string Addr string
Chain *Chain Chain *Chain
Users []*url.Userinfo Users []*url.Userinfo
TLSConfig *tls.Config TLSConfig *tls.Config
Whitelist *Permissions Whitelist *Permissions
Blacklist *Permissions Blacklist *Permissions
RedisClient *redis.Client
} }
// HandlerOption allows a common way to set handler options. // HandlerOption allows a common way to set handler options.
@ -71,6 +73,13 @@ func BlacklistHandlerOption(blacklist *Permissions) HandlerOption {
} }
} }
// RedisClientHandlerOption sets the RedisClient option of HandlerOptions.
func RedisClientHandlerOption(client *redis.Client) HandlerOption {
return func(opts *HandlerOptions) {
opts.RedisClient = client
}
}
type autoHandler struct { type autoHandler struct {
options []HandlerOption options []HandlerOption
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/ginuerzh/gosocks4" "github.com/ginuerzh/gosocks4"
"github.com/ginuerzh/gosocks5" "github.com/ginuerzh/gosocks5"
"github.com/go-log/log" "github.com/go-log/log"
"github.com/go-redis/redis"
) )
const ( const (
@ -90,9 +91,10 @@ func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Con
} }
type serverSelector struct { type serverSelector struct {
methods []uint8 methods []uint8
Users []*url.Userinfo Users []*url.Userinfo
TLSConfig *tls.Config TLSConfig *tls.Config
RedisClient *redis.Client
} }
func (selector *serverSelector) Methods() []uint8 { func (selector *serverSelector) Methods() []uint8 {
@ -116,7 +118,7 @@ func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
} }
// when user/pass is set, auth is mandatory // when user/pass is set, auth is mandatory
if len(selector.Users) > 0 { if len(selector.Users) > 0 || selector.RedisClient != nil {
if method == gosocks5.MethodNoAuth { if method == gosocks5.MethodNoAuth {
method = gosocks5.MethodUserPass method = gosocks5.MethodUserPass
} }
@ -150,17 +152,25 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
log.Log("[socks5]", req.String()) log.Log("[socks5]", req.String())
} }
valid := false valid := false
for _, user := range selector.Users { if selector.RedisClient != nil {
username := user.Username() password, err := selector.RedisClient.Get(req.Username).Result()
password, _ := user.Password() if err == nil && req.Password == password {
if (req.Username == username && req.Password == password) ||
(req.Username == username && password == "") ||
(username == "" && req.Password == password) {
valid = true valid = true
break
} }
} }
if len(selector.Users) > 0 && !valid { if len(selector.Users) > 0 {
for _, user := range selector.Users {
username := user.Username()
password, _ := user.Password()
if (req.Username == username && req.Password == password) ||
(req.Username == username && password == "") ||
(username == "" && req.Password == password) {
valid = true
break
}
}
}
if (selector.RedisClient != nil || len(selector.Users) > 0) && !valid {
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure) resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
if err := resp.Write(conn); err != nil { if err := resp.Write(conn); err != nil {
log.Log("[socks5]", err) log.Log("[socks5]", err)
@ -353,8 +363,9 @@ func SOCKS5Handler(opts ...HandlerOption) Handler {
tlsConfig = DefaultTLSConfig tlsConfig = DefaultTLSConfig
} }
selector := &serverSelector{ // socks5 server selector selector := &serverSelector{ // socks5 server selector
Users: options.Users, Users: options.Users,
TLSConfig: tlsConfig, TLSConfig: tlsConfig,
RedisClient: options.RedisClient,
} }
// methods that socks5 server supported // methods that socks5 server supported
selector.AddMethod( selector.AddMethod(