271 lines
6.5 KiB
Go
271 lines
6.5 KiB
Go
package gost
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/tls"
|
|
"net"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/go-gost/gosocks4"
|
|
"github.com/go-gost/gosocks5"
|
|
"github.com/go-log/log"
|
|
)
|
|
|
|
// Handler is a proxy server handler
|
|
type Handler interface {
|
|
Init(options ...HandlerOption)
|
|
Handle(net.Conn)
|
|
}
|
|
|
|
// HandlerOptions describes the options for Handler.
|
|
type HandlerOptions struct {
|
|
Addr string
|
|
Chain *Chain
|
|
Users []*url.Userinfo
|
|
Authenticator Authenticator
|
|
TLSConfig *tls.Config
|
|
Whitelist *Permissions
|
|
Blacklist *Permissions
|
|
Strategy Strategy
|
|
MaxFails int
|
|
FailTimeout time.Duration
|
|
Bypass *Bypass
|
|
Retries int
|
|
Timeout time.Duration
|
|
Resolver Resolver
|
|
Hosts *Hosts
|
|
ProbeResist string
|
|
KnockingHost string
|
|
Node Node
|
|
Host string
|
|
IPs []string
|
|
TCPMode bool
|
|
IPRoutes []IPRoute
|
|
}
|
|
|
|
// HandlerOption allows a common way to set handler options.
|
|
type HandlerOption func(opts *HandlerOptions)
|
|
|
|
// AddrHandlerOption sets the Addr option of HandlerOptions.
|
|
func AddrHandlerOption(addr string) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Addr = addr
|
|
}
|
|
}
|
|
|
|
// ChainHandlerOption sets the Chain option of HandlerOptions.
|
|
func ChainHandlerOption(chain *Chain) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Chain = chain
|
|
}
|
|
}
|
|
|
|
// UsersHandlerOption sets the Users option of HandlerOptions.
|
|
func UsersHandlerOption(users ...*url.Userinfo) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Users = users
|
|
|
|
kvs := make(map[string]string)
|
|
for _, u := range users {
|
|
if u != nil {
|
|
kvs[u.Username()], _ = u.Password()
|
|
}
|
|
}
|
|
if len(kvs) > 0 {
|
|
opts.Authenticator = NewLocalAuthenticator(kvs)
|
|
}
|
|
}
|
|
}
|
|
|
|
// AuthenticatorHandlerOption sets the Authenticator option of HandlerOptions.
|
|
func AuthenticatorHandlerOption(au Authenticator) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Authenticator = au
|
|
}
|
|
}
|
|
|
|
// TLSConfigHandlerOption sets the TLSConfig option of HandlerOptions.
|
|
func TLSConfigHandlerOption(config *tls.Config) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.TLSConfig = config
|
|
}
|
|
}
|
|
|
|
// WhitelistHandlerOption sets the Whitelist option of HandlerOptions.
|
|
func WhitelistHandlerOption(whitelist *Permissions) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Whitelist = whitelist
|
|
}
|
|
}
|
|
|
|
// BlacklistHandlerOption sets the Blacklist option of HandlerOptions.
|
|
func BlacklistHandlerOption(blacklist *Permissions) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Blacklist = blacklist
|
|
}
|
|
}
|
|
|
|
// BypassHandlerOption sets the bypass option of HandlerOptions.
|
|
func BypassHandlerOption(bypass *Bypass) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Bypass = bypass
|
|
}
|
|
}
|
|
|
|
// StrategyHandlerOption sets the strategy option of HandlerOptions.
|
|
func StrategyHandlerOption(strategy Strategy) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Strategy = strategy
|
|
}
|
|
}
|
|
|
|
// MaxFailsHandlerOption sets the max_fails option of HandlerOptions.
|
|
func MaxFailsHandlerOption(n int) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.MaxFails = n
|
|
}
|
|
}
|
|
|
|
// FailTimeoutHandlerOption sets the fail_timeout option of HandlerOptions.
|
|
func FailTimeoutHandlerOption(d time.Duration) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.FailTimeout = d
|
|
}
|
|
}
|
|
|
|
// RetryHandlerOption sets the retry option of HandlerOptions.
|
|
func RetryHandlerOption(retries int) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Retries = retries
|
|
}
|
|
}
|
|
|
|
// TimeoutHandlerOption sets the timeout option of HandlerOptions.
|
|
func TimeoutHandlerOption(timeout time.Duration) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Timeout = timeout
|
|
}
|
|
}
|
|
|
|
// ResolverHandlerOption sets the resolver option of HandlerOptions.
|
|
func ResolverHandlerOption(resolver Resolver) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Resolver = resolver
|
|
}
|
|
}
|
|
|
|
// HostsHandlerOption sets the Hosts option of HandlerOptions.
|
|
func HostsHandlerOption(hosts *Hosts) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Hosts = hosts
|
|
}
|
|
}
|
|
|
|
// ProbeResistHandlerOption adds the probe resistance for HTTP proxy.
|
|
func ProbeResistHandlerOption(pr string) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.ProbeResist = pr
|
|
}
|
|
}
|
|
|
|
// KnockingHandlerOption adds the knocking host for probe resistance.
|
|
func KnockingHandlerOption(host string) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.KnockingHost = host
|
|
}
|
|
}
|
|
|
|
// NodeHandlerOption set the server node for server handler.
|
|
func NodeHandlerOption(node Node) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Node = node
|
|
}
|
|
}
|
|
|
|
// HostHandlerOption sets the target host for SNI proxy.
|
|
func HostHandlerOption(host string) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.Host = host
|
|
}
|
|
}
|
|
|
|
// IPsHandlerOption sets the ip list for port forward.
|
|
func IPsHandlerOption(ips []string) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.IPs = ips
|
|
}
|
|
}
|
|
|
|
// TCPModeHandlerOption sets the tcp mode for tun/tap device.
|
|
func TCPModeHandlerOption(b bool) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.TCPMode = b
|
|
}
|
|
}
|
|
|
|
// IPRoutesHandlerOption sets the IP routes for tun tunnel.
|
|
func IPRoutesHandlerOption(routes ...IPRoute) HandlerOption {
|
|
return func(opts *HandlerOptions) {
|
|
opts.IPRoutes = routes
|
|
}
|
|
}
|
|
|
|
type autoHandler struct {
|
|
options *HandlerOptions
|
|
}
|
|
|
|
// AutoHandler creates a server Handler for auto proxy server.
|
|
func AutoHandler(opts ...HandlerOption) Handler {
|
|
h := &autoHandler{}
|
|
h.Init(opts...)
|
|
return h
|
|
}
|
|
|
|
func (h *autoHandler) Init(options ...HandlerOption) {
|
|
if h.options == nil {
|
|
h.options = &HandlerOptions{}
|
|
}
|
|
for _, opt := range options {
|
|
opt(h.options)
|
|
}
|
|
}
|
|
|
|
func (h *autoHandler) Handle(conn net.Conn) {
|
|
br := bufio.NewReader(conn)
|
|
b, err := br.Peek(1)
|
|
if err != nil {
|
|
log.Logf("[auto] %s - %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err)
|
|
conn.Close()
|
|
return
|
|
}
|
|
|
|
cc := &bufferdConn{Conn: conn, br: br}
|
|
var handler Handler
|
|
switch b[0] {
|
|
case gosocks4.Ver4:
|
|
// SOCKS4(a) does not suppport authentication method,
|
|
// so we ignore it when credentials are specified for security reason.
|
|
if len(h.options.Users) > 0 {
|
|
cc.Close()
|
|
return
|
|
}
|
|
handler = &socks4Handler{options: h.options}
|
|
case gosocks5.Ver5: // socks5
|
|
handler = &socks5Handler{options: h.options}
|
|
default: // http
|
|
handler = &httpHandler{options: h.options}
|
|
}
|
|
handler.Init()
|
|
handler.Handle(cc)
|
|
}
|
|
|
|
type bufferdConn struct {
|
|
net.Conn
|
|
br *bufio.Reader
|
|
}
|
|
|
|
func (c *bufferdConn) Read(b []byte) (int, error) {
|
|
return c.br.Read(b)
|
|
}
|