add Handler.Init

This commit is contained in:
ginuerzh 2018-07-06 15:25:08 +08:00
parent 644d22d7c3
commit c242286a06
13 changed files with 301 additions and 172 deletions

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"time"
"github.com/go-log/log" "github.com/go-log/log"
) )
@ -308,3 +309,42 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
} }
return return
} }
// ChainOptions holds options for Chain.
type ChainOptions struct {
Retry int
Timeout time.Duration
Hosts *Hosts
Resolver Resolver
}
// ChainOption allows a common way to set chain options.
type ChainOption func(opts *ChainOptions)
// RetryChainOption specifies the times of retry used by Chain.Dial.
func RetryChainOption(retry int) ChainOption {
return func(opts *ChainOptions) {
opts.Retry = retry
}
}
// TimeoutChainOption specifies the timeout used by Chain.Dial.
func TimeoutChainOption(timeout time.Duration) ChainOption {
return func(opts *ChainOptions) {
opts.Timeout = timeout
}
}
// HostsChainOption specifies the hosts used by Chain.Dial.
func HostsChainOption(hosts *Hosts) ChainOption {
return func(opts *ChainOptions) {
opts.Hosts = hosts
}
}
// ResolverChainOption specifies the Resolver used by Chain.Dial.
func ResolverChainOption(resolver Resolver) ChainOption {
return func(opts *ChainOptions) {
opts.Resolver = resolver
}
}

View File

@ -90,7 +90,7 @@ func (tr *tcpTransporter) Multiplex() bool {
return false return false
} }
// DialOptions describes the options for dialing. // DialOptions describes the options for Transporter.Dial.
type DialOptions struct { type DialOptions struct {
Timeout time.Duration Timeout time.Duration
Chain *Chain Chain *Chain

View File

@ -341,15 +341,12 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
} }
func (r *route) serve() error { func (r *route) serve() error {
baseChain, err := r.initChain() chain, err := r.initChain()
if err != nil { if err != nil {
return err return err
} }
for _, ns := range r.ServeNodes { for _, ns := range r.ServeNodes {
chain := &gost.Chain{}
*chain = *baseChain
node, err := gost.ParseNode(ns) node, err := gost.ParseNode(ns)
if err != nil { if err != nil {
return err return err
@ -469,8 +466,43 @@ func (r *route) serve() error {
} }
} }
var handlerOptions []gost.HandlerOption var handler gost.Handler
handlerOptions = append(handlerOptions, switch node.Protocol {
case "http2":
handler = gost.HTTP2Handler()
case "socks", "socks5":
handler = gost.SOCKS5Handler()
case "socks4", "socks4a":
handler = gost.SOCKS4Handler()
case "ss":
handler = gost.ShadowHandler()
case "http":
handler = gost.HTTPHandler()
case "tcp":
handler = gost.TCPDirectForwardHandler(node.Remote)
case "rtcp":
handler = gost.TCPRemoteForwardHandler(node.Remote)
case "udp":
handler = gost.UDPDirectForwardHandler(node.Remote)
case "rudp":
handler = gost.UDPRemoteForwardHandler(node.Remote)
case "forward":
handler = gost.SSHForwardHandler()
case "redirect":
handler = gost.TCPRedirectHandler()
case "ssu":
handler = gost.ShadowUDPdHandler()
case "sni":
handler = gost.SNIHandler()
default:
// start from 2.5, if remote is not empty, then we assume that it is a forward tunnel.
if node.Remote != "" {
handler = gost.TCPDirectForwardHandler(node.Remote)
} else {
handler = gost.AutoHandler()
}
}
handler.Init(
gost.AddrHandlerOption(node.Addr), gost.AddrHandlerOption(node.Addr),
gost.ChainHandlerOption(chain), gost.ChainHandlerOption(chain),
gost.UsersHandlerOption(users...), gost.UsersHandlerOption(users...),
@ -480,44 +512,6 @@ func (r *route) serve() error {
gost.BypassHandlerOption(parseBypass(node.Get("bypass"))), gost.BypassHandlerOption(parseBypass(node.Get("bypass"))),
gost.StrategyHandlerOption(parseStrategy(node.Get("strategy"))), gost.StrategyHandlerOption(parseStrategy(node.Get("strategy"))),
) )
var handler gost.Handler
switch node.Protocol {
case "http2":
handler = gost.HTTP2Handler(handlerOptions...)
case "socks", "socks5":
handler = gost.SOCKS5Handler(handlerOptions...)
case "socks4", "socks4a":
handler = gost.SOCKS4Handler(handlerOptions...)
case "ss":
handler = gost.ShadowHandler(handlerOptions...)
case "http":
handler = gost.HTTPHandler(handlerOptions...)
case "tcp":
handler = gost.TCPDirectForwardHandler(node.Remote, handlerOptions...)
case "rtcp":
handler = gost.TCPRemoteForwardHandler(node.Remote, handlerOptions...)
case "udp":
handler = gost.UDPDirectForwardHandler(node.Remote, handlerOptions...)
case "rudp":
handler = gost.UDPRemoteForwardHandler(node.Remote, handlerOptions...)
case "forward":
handler = gost.SSHForwardHandler(handlerOptions...)
case "redirect":
handler = gost.TCPRedirectHandler(handlerOptions...)
case "ssu":
handler = gost.ShadowUDPdHandler(handlerOptions...)
case "sni":
handler = gost.SNIHandler(handlerOptions...)
default:
// start from 2.5, if remote is not empty, then we assume that it is a forward tunnel.
if node.Remote != "" {
handler = gost.TCPDirectForwardHandler(node.Remote, handlerOptions...)
} else {
handler = gost.AutoHandler(handlerOptions...)
}
}
srv := &gost.Server{Listener: ln}
chain.Resolver = parseResolver(node.Get("dns")) chain.Resolver = parseResolver(node.Get("dns"))
if gost.Debug { if gost.Debug {
@ -531,6 +525,7 @@ func (r *route) serve() error {
} }
} }
srv := &gost.Server{Listener: ln}
go srv.Serve(handler) go srv.Serve(handler)
} }

View File

@ -37,21 +37,9 @@ type tcpDirectForwardHandler struct {
// NOTE: as of 2.6, remote address can be a comma-separated address list. // NOTE: as of 2.6, remote address can be a comma-separated address list.
func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler { func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &tcpDirectForwardHandler{ h := &tcpDirectForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, group: NewNodeGroup(),
} }
for _, opt := range opts {
opt(h.options)
}
group := NewNodeGroup()
group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
for i, addr := range strings.Split(raddr, ",") { for i, addr := range strings.Split(raddr, ",") {
if addr == "" { if addr == "" {
@ -59,17 +47,35 @@ func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
} }
// We treat the remote target server as a node, so we can put them in a group, // We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing. // and perform the node selection for load balancing.
group.AddNode(Node{ h.group.AddNode(Node{
ID: i + 1, ID: i + 1,
Addr: addr, Addr: addr,
Host: addr, Host: addr,
}) })
} }
h.group = group h.Init(opts...)
return h return h
} }
func (h *tcpDirectForwardHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
h.group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
}
func (h *tcpDirectForwardHandler) Handle(conn net.Conn) { func (h *tcpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
@ -106,21 +112,9 @@ type udpDirectForwardHandler struct {
// NOTE: as of 2.6, remote address can be a comma-separated address list. // NOTE: as of 2.6, remote address can be a comma-separated address list.
func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler { func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &udpDirectForwardHandler{ h := &udpDirectForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, group: NewNodeGroup(),
} }
for _, opt := range opts {
opt(h.options)
}
group := NewNodeGroup()
group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
for i, addr := range strings.Split(raddr, ",") { for i, addr := range strings.Split(raddr, ",") {
if addr == "" { if addr == "" {
@ -128,17 +122,36 @@ func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
} }
// We treat the remote target server as a node, so we can put them in a group, // We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing. // and perform the node selection for load balancing.
group.AddNode(Node{ h.group.AddNode(Node{
ID: i + 1, ID: i + 1,
Addr: addr, Addr: addr,
Host: addr, Host: addr,
}) })
} }
h.group = group
h.Init(opts...)
return h return h
} }
func (h *udpDirectForwardHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
h.group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
}
func (h *udpDirectForwardHandler) Handle(conn net.Conn) { func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
@ -191,21 +204,9 @@ type tcpRemoteForwardHandler struct {
// NOTE: as of 2.6, remote address can be a comma-separated address list. // NOTE: as of 2.6, remote address can be a comma-separated address list.
func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler { func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &tcpRemoteForwardHandler{ h := &tcpRemoteForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, group: NewNodeGroup(),
} }
for _, opt := range opts {
opt(h.options)
}
group := NewNodeGroup()
group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
for i, addr := range strings.Split(raddr, ",") { for i, addr := range strings.Split(raddr, ",") {
if addr == "" { if addr == "" {
@ -213,17 +214,34 @@ func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
} }
// We treat the remote target server as a node, so we can put them in a group, // We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing. // and perform the node selection for load balancing.
group.AddNode(Node{ h.group.AddNode(Node{
ID: i + 1, ID: i + 1,
Addr: addr, Addr: addr,
Host: addr, Host: addr,
}) })
} }
h.group = group h.Init(opts...)
return h return h
} }
func (h *tcpRemoteForwardHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
h.group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
}
func (h *tcpRemoteForwardHandler) Handle(conn net.Conn) { func (h *tcpRemoteForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
@ -258,38 +276,45 @@ type udpRemoteForwardHandler struct {
// NOTE: as of 2.6, remote address can be a comma-separated address list. // NOTE: as of 2.6, remote address can be a comma-separated address list.
func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler { func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
h := &udpRemoteForwardHandler{ h := &udpRemoteForwardHandler{
raddr: raddr, raddr: raddr,
options: &HandlerOptions{}, group: NewNodeGroup(),
}
for _, opt := range opts {
opt(h.options)
} }
group := NewNodeGroup()
group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
for i, addr := range strings.Split(raddr, ",") { for i, addr := range strings.Split(raddr, ",") {
if addr == "" { if addr == "" {
continue continue
} }
// We treat the remote target server as a node, so we can put them in a group, // We treat the remote target server as a node, so we can put them in a group,
// and perform the node selection for load balancing. // and perform the node selection for load balancing.
group.AddNode(Node{ h.group.AddNode(Node{
ID: i + 1, ID: i + 1,
Addr: addr, Addr: addr,
Host: addr, Host: addr,
}) })
} }
h.group = group
h.Init(opts...)
return h return h
} }
func (h *udpRemoteForwardHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
h.group.SetSelector(&defaultSelector{},
WithStrategy(h.options.Strategy),
WithFilter(&FailFilter{
MaxFails: 1,
FailTimeout: 30 * time.Second,
}),
)
}
func (h *udpRemoteForwardHandler) Handle(conn net.Conn) { func (h *udpRemoteForwardHandler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()

View File

@ -13,6 +13,7 @@ import (
// Handler is a proxy server handler // Handler is a proxy server handler
type Handler interface { type Handler interface {
Init(options ...HandlerOption)
Handle(net.Conn) Handle(net.Conn)
} }
@ -88,17 +89,25 @@ func StrategyHandlerOption(strategy Strategy) HandlerOption {
} }
type autoHandler struct { type autoHandler struct {
options []HandlerOption options *HandlerOptions
} }
// AutoHandler creates a server Handler for auto proxy server. // AutoHandler creates a server Handler for auto proxy server.
func AutoHandler(opts ...HandlerOption) Handler { func AutoHandler(opts ...HandlerOption) Handler {
h := &autoHandler{ h := &autoHandler{}
options: opts, h.Init(opts...)
}
return h 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) { func (h *autoHandler) Handle(conn net.Conn) {
br := bufio.NewReader(conn) br := bufio.NewReader(conn)
b, err := br.Peek(1) b, err := br.Peek(1)
@ -109,25 +118,23 @@ func (h *autoHandler) Handle(conn net.Conn) {
} }
cc := &bufferdConn{Conn: conn, br: br} cc := &bufferdConn{Conn: conn, br: br}
var handler Handler
switch b[0] { switch b[0] {
case gosocks4.Ver4: case gosocks4.Ver4:
options := &HandlerOptions{}
for _, opt := range h.options {
opt(options)
}
// SOCKS4(a) does not suppport authentication method, // SOCKS4(a) does not suppport authentication method,
// so we ignore it when credentials are specified for security reason. // so we ignore it when credentials are specified for security reason.
if len(options.Users) > 0 { if len(h.options.Users) > 0 {
cc.Close() cc.Close()
return return
} }
h := &socks4Handler{options} handler = &socks4Handler{options: h.options}
h.Handle(cc) case gosocks5.Ver5: // socks5
case gosocks5.Ver5: handler = &socks5Handler{options: h.options}
SOCKS5Handler(h.options...).Handle(cc)
default: // http default: // http
HTTPHandler(h.options...).Handle(cc) handler = &httpHandler{options: h.options}
} }
handler.Init()
handler.Handle(cc)
} }
type bufferdConn struct { type bufferdConn struct {

13
http.go
View File

@ -75,13 +75,18 @@ type httpHandler struct {
// HTTPHandler creates a server Handler for HTTP proxy server. // HTTPHandler creates a server Handler for HTTP proxy server.
func HTTPHandler(opts ...HandlerOption) Handler { func HTTPHandler(opts ...HandlerOption) Handler {
h := &httpHandler{ h := &httpHandler{}
options: &HandlerOptions{}, h.Init(opts...)
return h
}
func (h *httpHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
for _, opt := range opts { for _, opt := range options {
opt(h.options) opt(h.options)
} }
return h
} }
func (h *httpHandler) Handle(conn net.Conn) { func (h *httpHandler) Handle(conn net.Conn) {

View File

@ -250,16 +250,21 @@ type http2Handler struct {
// HTTP2Handler creates a server Handler for HTTP2 proxy server. // HTTP2Handler creates a server Handler for HTTP2 proxy server.
func HTTP2Handler(opts ...HandlerOption) Handler { func HTTP2Handler(opts ...HandlerOption) Handler {
h := &http2Handler{ h := &http2Handler{}
options: new(HandlerOptions), h.Init(opts...)
}
for _, opt := range opts {
opt(h.options)
}
return h return h
} }
func (h *http2Handler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
}
for _, opt := range options {
opt(h.options)
}
}
func (h *http2Handler) Handle(conn net.Conn) { func (h *http2Handler) Handle(conn net.Conn) {
defer conn.Close() defer conn.Close()

View File

@ -17,15 +17,20 @@ type tcpRedirectHandler struct {
// TCPRedirectHandler creates a server Handler for TCP redirect server. // TCPRedirectHandler creates a server Handler for TCP redirect server.
func TCPRedirectHandler(opts ...HandlerOption) Handler { func TCPRedirectHandler(opts ...HandlerOption) Handler {
h := &tcpRedirectHandler{ h := &tcpRedirectHandler{}
options: &HandlerOptions{ h.Init(opts...)
Chain: new(Chain),
}, return h
}
func (h *tcpRedirectHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
for _, opt := range opts {
for _, opt := range options {
opt(h.options) opt(h.options)
} }
return h
} }
func (h *tcpRedirectHandler) Handle(c net.Conn) { func (h *tcpRedirectHandler) Handle(c net.Conn) {

View File

@ -48,6 +48,12 @@ func (ns NameServer) String() string {
return fmt.Sprintf("%s/%s %s", addr, prot, host) return fmt.Sprintf("%s/%s %s", addr, prot, host)
} }
type nameServers struct {
Servers []NameServer
Timeout time.Duration
TTL time.Duration
}
type resolverCacheItem struct { type resolverCacheItem struct {
IPs []net.IP IPs []net.IP
ts int64 ts int64

15
sni.go
View File

@ -38,13 +38,20 @@ type sniHandler struct {
// SNIHandler creates a server Handler for SNI proxy server. // SNIHandler creates a server Handler for SNI proxy server.
func SNIHandler(opts ...HandlerOption) Handler { func SNIHandler(opts ...HandlerOption) Handler {
h := &sniHandler{ h := &sniHandler{}
options: &HandlerOptions{}, h.Init(opts...)
return h
}
func (h *sniHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
for _, opt := range opts {
for _, opt := range options {
opt(h.options) opt(h.options)
} }
return h
} }
func (h *sniHandler) Handle(conn net.Conn) { func (h *sniHandler) Handle(conn net.Conn) {

View File

@ -348,30 +348,36 @@ type socks5Handler struct {
// SOCKS5Handler creates a server Handler for SOCKS5 proxy server. // SOCKS5Handler creates a server Handler for SOCKS5 proxy server.
func SOCKS5Handler(opts ...HandlerOption) Handler { func SOCKS5Handler(opts ...HandlerOption) Handler {
options := &HandlerOptions{} h := &socks5Handler{}
for _, opt := range opts { h.Init(opts...)
opt(options)
return h
}
func (h *socks5Handler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
tlsConfig := options.TLSConfig for _, opt := range options {
opt(h.options)
}
tlsConfig := h.options.TLSConfig
if tlsConfig == nil { if tlsConfig == nil {
tlsConfig = DefaultTLSConfig tlsConfig = DefaultTLSConfig
} }
selector := &serverSelector{ // socks5 server selector h.selector = &serverSelector{ // socks5 server selector
Users: options.Users, Users: h.options.Users,
TLSConfig: tlsConfig, TLSConfig: tlsConfig,
} }
// methods that socks5 server supported // methods that socks5 server supported
selector.AddMethod( h.selector.AddMethod(
gosocks5.MethodNoAuth, gosocks5.MethodNoAuth,
gosocks5.MethodUserPass, gosocks5.MethodUserPass,
MethodTLS, MethodTLS,
MethodTLSAuth, MethodTLSAuth,
) )
return &socks5Handler{
options: options,
selector: selector,
}
} }
func (h *socks5Handler) Handle(conn net.Conn) { func (h *socks5Handler) Handle(conn net.Conn) {
@ -1110,12 +1116,19 @@ type socks4Handler struct {
// SOCKS4Handler creates a server Handler for SOCKS4(A) proxy server. // SOCKS4Handler creates a server Handler for SOCKS4(A) proxy server.
func SOCKS4Handler(opts ...HandlerOption) Handler { func SOCKS4Handler(opts ...HandlerOption) Handler {
options := &HandlerOptions{} h := &socks4Handler{}
for _, opt := range opts { h.Init(opts...)
opt(options)
return h
}
func (h *socks4Handler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
return &socks4Handler{
options: options, for _, opt := range options {
opt(h.options)
} }
} }

30
ss.go
View File

@ -97,13 +97,20 @@ type shadowHandler struct {
// ShadowHandler creates a server Handler for shadowsocks proxy server. // ShadowHandler creates a server Handler for shadowsocks proxy server.
func ShadowHandler(opts ...HandlerOption) Handler { func ShadowHandler(opts ...HandlerOption) Handler {
h := &shadowHandler{ h := &shadowHandler{}
options: &HandlerOptions{}, h.Init(opts...)
return h
}
func (h *shadowHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
for _, opt := range opts {
for _, opt := range options {
opt(h.options) opt(h.options)
} }
return h
} }
func (h *shadowHandler) Handle(conn net.Conn) { func (h *shadowHandler) Handle(conn net.Conn) {
@ -326,13 +333,20 @@ type shadowUDPdHandler struct {
// ShadowUDPdHandler creates a server Handler for shadowsocks UDP relay server. // ShadowUDPdHandler creates a server Handler for shadowsocks UDP relay server.
func ShadowUDPdHandler(opts ...HandlerOption) Handler { func ShadowUDPdHandler(opts ...HandlerOption) Handler {
h := &shadowUDPdHandler{ h := &shadowUDPdHandler{}
options: &HandlerOptions{}, h.Init(opts...)
return h
}
func (h *shadowUDPdHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
for _, opt := range opts {
for _, opt := range options {
opt(h.options) opt(h.options)
} }
return h
} }
func (h *shadowUDPdHandler) Handle(conn net.Conn) { func (h *shadowUDPdHandler) Handle(conn net.Conn) {

19
ssh.go
View File

@ -408,13 +408,22 @@ type sshForwardHandler struct {
// SSHForwardHandler creates a server Handler for SSH port forwarding server. // SSHForwardHandler creates a server Handler for SSH port forwarding server.
func SSHForwardHandler(opts ...HandlerOption) Handler { func SSHForwardHandler(opts ...HandlerOption) Handler {
h := &sshForwardHandler{ h := &sshForwardHandler{}
options: new(HandlerOptions), h.Init(opts...)
config: new(ssh.ServerConfig),
return h
}
func (h *sshForwardHandler) Init(options ...HandlerOption) {
if h.options == nil {
h.options = &HandlerOptions{}
} }
for _, opt := range opts {
for _, opt := range options {
opt(h.options) opt(h.options)
} }
h.config = &ssh.ServerConfig{}
h.config.PasswordCallback = defaultSSHPasswordCallback(h.options.Users...) h.config.PasswordCallback = defaultSSHPasswordCallback(h.options.Users...)
if len(h.options.Users) == 0 { if len(h.options.Users) == 0 {
h.config.NoClientAuth = true h.config.NoClientAuth = true
@ -430,8 +439,6 @@ func SSHForwardHandler(opts ...HandlerOption) Handler {
} }
h.config.AddHostKey(signer) h.config.AddHostKey(signer)
} }
return h
} }
func (h *sshForwardHandler) Handle(conn net.Conn) { func (h *sshForwardHandler) Handle(conn net.Conn) {