Commit 684ccca2 authored by rui.zheng's avatar rui.zheng

add socks4/5 server handlers

parent 7402fb24
package gost package gost
import ( import (
"errors"
"net" "net"
) )
var (
// ErrEmptyChain is an error that implies the chain is empty
ErrEmptyChain = errors.New("empty chain")
)
// Chain is a proxy chain that holds a list of proxy nodes.
type Chain struct { type Chain struct {
Nodes []Node nodes []Node
} }
// NewChain creates a proxy chain with proxy nodes nodes.
func NewChain(nodes ...Node) *Chain { func NewChain(nodes ...Node) *Chain {
return &Chain{ return &Chain{
Nodes: nodes, nodes: nodes,
}
}
// Nodes returns the proxy nodes that the chain holds.
func (c *Chain) Nodes() []Node {
return c.nodes
}
// LastNode returns the last node of the node list.
// If the chain is empty, an empty node is returns.
func (c *Chain) LastNode() Node {
if c.IsEmpty() {
return Node{}
} }
return c.nodes[len(c.nodes)-1]
}
// AddNode appends the node(s) to the chain.
func (c *Chain) AddNode(nodes ...Node) {
c.nodes = append(c.nodes, nodes...)
}
// IsEmpty checks if the chain is empty.
// An empty chain means that there is no proxy node in the chain.
func (c *Chain) IsEmpty() bool {
return len(c.nodes) == 0
} }
// Dial connects to the target address addr through the chain.
// If the chain is empty, it will use the net.Dial directly.
func (c *Chain) Dial(addr string) (net.Conn, error) { func (c *Chain) Dial(addr string) (net.Conn, error) {
if len(c.Nodes) == 0 { if c.IsEmpty() {
return net.Dial("tcp", addr) return net.Dial("tcp", addr)
} }
nodes := c.Nodes conn, err := c.Conn()
if err != nil {
return nil, err
}
cc, err := c.LastNode().Client.Connect(conn, addr)
if err != nil {
conn.Close()
return nil, err
}
return cc, nil
}
// Conn obtains a handshaked connection to the last node of the chain.
// If the chain is empty, it returns an ErrEmptyChain error.
func (c *Chain) Conn() (net.Conn, error) {
if c.IsEmpty() {
return nil, ErrEmptyChain
}
nodes := c.nodes
conn, err := nodes[0].Client.Dial(nodes[0].Addr) conn, err := nodes[0].Client.Dial(nodes[0].Addr)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -46,14 +101,7 @@ func (c *Chain) Dial(addr string) (net.Conn, error) { ...@@ -46,14 +101,7 @@ func (c *Chain) Dial(addr string) (net.Conn, error) {
conn.Close() conn.Close()
return nil, err return nil, err
} }
conn = cc conn = cc
} }
return conn, nil
cc, err := nodes[len(nodes)-1].Client.Connect( conn, addr)
if err != nil {
conn.Close()
return nil, err
}
return cc, nil
} }
...@@ -2,11 +2,9 @@ package main ...@@ -2,11 +2,9 @@ package main
import ( import (
"bufio" "bufio"
"crypto/tls"
"log" "log"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"github.com/ginuerzh/gost/gost" "github.com/ginuerzh/gost/gost"
...@@ -20,60 +18,73 @@ func init() { ...@@ -20,60 +18,73 @@ func init() {
func main() { func main() {
chain := gost.NewChain( chain := gost.NewChain(
/* /*
// http+ws // http+tcp
gost.Node{ gost.Node{
Addr: "127.0.0.1:8000", Addr: "127.0.0.1:8080",
Client: gost.NewClient( Client: gost.NewClient(
gost.HTTPConnector(url.UserPassword("admin", "123456")), gost.HTTPConnector(url.UserPassword("admin", "123456")),
gost.WSTransporter("127.0.0.1:8000", nil), gost.TCPTransporter(),
), ),
}, },
*/ */
// http+wss // socks5+tcp
gost.Node{ gost.Node{
Addr: "127.0.0.1:8443", Addr: "127.0.0.1:1080",
Client: gost.NewClient( Client: gost.NewClient(
gost.HTTPConnector(url.UserPassword("admin", "123456")), gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
gost.WSSTransporter( gost.TCPTransporter(),
"127.0.0.1:8443",
&gost.WSOptions{TLSConfig: &tls.Config{InsecureSkipVerify: true}},
),
), ),
}, },
/* /*
// http+tcp // ss+tcp
gost.Node{ gost.Node{
Addr: "127.0.0.1:1080", Addr: "127.0.0.1:8338",
Client: gost.NewClient( Client: gost.NewClient(
gost.HTTPConnector(url.UserPassword("admin", "123456")), gost.ShadowConnector(url.UserPassword("chacha20", "123456")),
gost.TCPTransporter(), gost.TCPTransporter(),
), ),
}, },
*/ */
/* /*
// http+tls // http+ws
gost.Node{ gost.Node{
Addr: "127.0.0.1:1443", Addr: "127.0.0.1:8000",
Client: gost.NewClient( Client: gost.NewClient(
gost.HTTPConnector(url.UserPassword("admin", "123456")), gost.HTTPConnector(url.UserPassword("admin", "123456")),
gost.TLSTransporter(&tls.Config{InsecureSkipVerify: true}), gost.WSTransporter("127.0.0.1:8000", nil),
), ),
}, },
*/ */
/* /*
// ss+tcp // http+wss
gost.Node{ gost.Node{
Addr: "127.0.0.1:8338", Addr: "127.0.0.1:8443",
Client: gost.NewClient( Client: gost.NewClient(
gost.ShadowConnector(url.UserPassword("chacha20", "123456")), gost.HTTPConnector(url.UserPassword("admin", "123456")),
gost.TCPTransporter(), gost.WSSTransporter(
"127.0.0.1:8443",
&gost.WSOptions{TLSConfig: &tls.Config{InsecureSkipVerify: true}},
),
),
},
*/
/*
// http+tls
gost.Node{
Addr: "127.0.0.1:1443",
Client: gost.NewClient(
gost.HTTPConnector(url.UserPassword("admin", "123456")),
gost.TLSTransporter(&tls.Config{InsecureSkipVerify: true}),
), ),
}, },
*/ */
) )
conn, err := chain.Dial("localhost:10000") conn, err := chain.Dial("localhost:10000")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
......
...@@ -4,11 +4,16 @@ import ( ...@@ -4,11 +4,16 @@ import (
"net" "net"
) )
// Client is a proxy client.
type Client struct { type Client struct {
Connector Connector Connector Connector
Transporter Transporter Transporter Transporter
} }
// NewClient creates a proxy client.
// A client is divided into two layers: connector and transporter.
// Connector is responsible for connecting to the destination address through this proxy.
// Transporter performs a handshake with this proxy.
func NewClient(c Connector, tr Transporter) *Client { func NewClient(c Connector, tr Transporter) *Client {
return &Client{ return &Client{
Connector: c, Connector: c,
...@@ -21,10 +26,14 @@ func (c *Client) Dial(addr string) (net.Conn, error) { ...@@ -21,10 +26,14 @@ func (c *Client) Dial(addr string) (net.Conn, error) {
return net.Dial(c.Transporter.Network(), addr) return net.Dial(c.Transporter.Network(), addr)
} }
// Handshake performs a handshake with the proxy.
// The conn should be an connection to this proxy.
func (c *Client) Handshake(conn net.Conn) (net.Conn, error) { func (c *Client) Handshake(conn net.Conn) (net.Conn, error) {
return c.Transporter.Handshake(conn) return c.Transporter.Handshake(conn)
} }
// Connect connects to the address addr via the proxy.
// The conn should be an connection to this proxy.
func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) { func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) {
return c.Connector.Connect(conn, addr) return c.Connector.Connect(conn, addr)
} }
...@@ -32,22 +41,27 @@ func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) { ...@@ -32,22 +41,27 @@ func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) {
// DefaultClient is a standard HTTP proxy client // DefaultClient is a standard HTTP proxy client
var DefaultClient = NewClient(HTTPConnector(nil), TCPTransporter()) var DefaultClient = NewClient(HTTPConnector(nil), TCPTransporter())
// Dial connects to the address addr via the DefaultClient.
func Dial(addr string) (net.Conn, error) { func Dial(addr string) (net.Conn, error) {
return DefaultClient.Dial(addr) return DefaultClient.Dial(addr)
} }
// Handshake performs a handshake via the DefaultClient
func Handshake(conn net.Conn) (net.Conn, error) { func Handshake(conn net.Conn) (net.Conn, error) {
return DefaultClient.Handshake(conn) return DefaultClient.Handshake(conn)
} }
// Connect connects to the address addr via the DefaultClient.
func Connect(conn net.Conn, addr string) (net.Conn, error) { func Connect(conn net.Conn, addr string) (net.Conn, error) {
return DefaultClient.Connect(conn, addr) return DefaultClient.Connect(conn, addr)
} }
// Connector is responsible for connecting to the destination address
type Connector interface { type Connector interface {
Connect(conn net.Conn, addr string) (net.Conn, error) Connect(conn net.Conn, addr string) (net.Conn, error)
} }
// Transporter is responsible for handshaking with the proxy server.
type Transporter interface { type Transporter interface {
Network() string Network() string
Handshake(conn net.Conn) (net.Conn, error) Handshake(conn net.Conn) (net.Conn, error)
......
package gost package gost
import ( import (
"time"
"github.com/go-log/log" "github.com/go-log/log"
) )
...@@ -9,11 +11,21 @@ const Version = "2.4-dev20170722" ...@@ -9,11 +11,21 @@ const Version = "2.4-dev20170722"
var Debug bool var Debug bool
var ( var (
TinyBufferSize = 128
SmallBufferSize = 1 * 1024 // 1KB small buffer SmallBufferSize = 1 * 1024 // 1KB small buffer
MediumBufferSize = 8 * 1024 // 8KB medium buffer MediumBufferSize = 8 * 1024 // 8KB medium buffer
LargeBufferSize = 32 * 1024 // 32KB large buffer LargeBufferSize = 32 * 1024 // 32KB large buffer
) )
var (
KeepAliveTime = 180 * time.Second
DialTimeout = 30 * time.Second
ReadTimeout = 90 * time.Second
WriteTimeout = 90 * time.Second
DefaultTTL = 60 // default udp node TTL in second for udp port forwarding
)
func init() { func init() {
log.DefaultLogger = &logger{} log.DefaultLogger = &logger{}
} }
package gost
import (
"crypto/tls"
"net"
"net/url"
)
type Handler interface {
Handle(net.Conn)
}
type HandlerOptions struct {
Chain *Chain
Users []*url.Userinfo
TLSConfig *tls.Config
}
type HandlerOption func(opts *HandlerOptions)
func ChainHandlerOption(chain *Chain) HandlerOption {
return func(opts *HandlerOptions) {
opts.Chain = chain
}
}
func UsersHandlerOption(users ...*url.Userinfo) HandlerOption {
return func(opts *HandlerOptions) {
opts.Users = users
}
}
func TLSConfigHandlerOption(config *tls.Config) HandlerOption {
return func(opts *HandlerOptions) {
opts.TLSConfig = config
}
}
package gost package gost
// Node is a proxy node, mainly used to construct a proxy chain
type Node struct { type Node struct {
Addr string Addr string
Protocol string Protocol string
......
package gost package gost
import ( import (
"crypto/tls"
"io" "io"
"net" "net"
"time" "time"
"net/url"
"github.com/go-log/log" "github.com/go-log/log"
) )
// Server is a proxy server.
type Server struct { type Server struct {
l net.Listener l net.Listener
handler Handler handler Handler
} }
// Handle sets a handler for the server
func (s *Server) Handle(h Handler) { func (s *Server) Handle(h Handler) {
s.handler = h s.handler = h
} }
// Serve serves as a proxy server.
func (s *Server) Serve(l net.Listener) error { func (s *Server) Serve(l net.Listener) error {
defer l.Close() defer l.Close()
...@@ -48,6 +48,7 @@ func (s *Server) Serve(l net.Listener) error { ...@@ -48,6 +48,7 @@ func (s *Server) Serve(l net.Listener) error {
} }
// Listener is a proxy server listener, just like a net.Listener.
type Listener interface { type Listener interface {
net.Listener net.Listener
} }
...@@ -64,34 +65,18 @@ func TCPListener(addr string) (Listener, error) { ...@@ -64,34 +65,18 @@ func TCPListener(addr string) (Listener, error) {
return &tcpListener{Listener: &tcpKeepAliveListener{ln.(*net.TCPListener)}}, nil return &tcpListener{Listener: &tcpKeepAliveListener{ln.(*net.TCPListener)}}, nil
} }
type Handler interface { type tcpKeepAliveListener struct {
Handle(net.Conn) *net.TCPListener
}
type HandlerOptions struct {
Chain *Chain
Users []*url.Userinfo
TLSConfig *tls.Config
}
type HandlerOption func(opts *HandlerOptions)
func ChainHandlerOption(chain *Chain) HandlerOption {
return func(opts *HandlerOptions) {
opts.Chain = chain
}
}
func UsersHandlerOption(users ...*url.Userinfo) HandlerOption {
return func(opts *HandlerOptions) {
opts.Users = users
}
} }
func TLSConfigHandlerOption(config *tls.Config) HandlerOption { func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
return func(opts *HandlerOptions) { tc, err := ln.AcceptTCP()
opts.TLSConfig = config if err != nil {
return
} }
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(KeepAliveTime)
return tc, nil
} }
func transport(rw1, rw2 io.ReadWriter) error { func transport(rw1, rw2 io.ReadWriter) error {
...@@ -106,23 +91,9 @@ func transport(rw1, rw2 io.ReadWriter) error { ...@@ -106,23 +91,9 @@ func transport(rw1, rw2 io.ReadWriter) error {
errc <- err errc <- err
}() }()
return <-errc err := <-errc
} if err != nil && err == io.EOF {
err = nil
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
} }
tc.SetKeepAlive(true) return err
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
} }
This diff is collapsed.
...@@ -21,6 +21,8 @@ func main() { ...@@ -21,6 +21,8 @@ func main() {
wg.Add(1) wg.Add(1)
go httpServer(&wg) go httpServer(&wg)
wg.Add(1) wg.Add(1)
go socks5Server(&wg)
wg.Add(1)
go tlsServer(&wg) go tlsServer(&wg)
wg.Add(1) wg.Add(1)
go shadowServer(&wg) go shadowServer(&wg)
...@@ -38,6 +40,26 @@ func httpServer(wg *sync.WaitGroup) { ...@@ -38,6 +40,26 @@ func httpServer(wg *sync.WaitGroup) {
s.Handle(gost.HTTPHandler( s.Handle(gost.HTTPHandler(
gost.UsersHandlerOption(url.UserPassword("admin", "123456")), gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
)) ))
ln, err := gost.TCPListener(":8080")
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
func socks5Server(wg *sync.WaitGroup) {
defer wg.Done()
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Fatal(err)
}
s := &gost.Server{}
s.Handle(gost.SOCKS5Handler(
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
gost.TLSConfigHandlerOption(&tls.Config{Certificates: []tls.Certificate{cert}}),
))
ln, err := gost.TCPListener(":1080") ln, err := gost.TCPListener(":1080")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
...@@ -45,6 +67,20 @@ func httpServer(wg *sync.WaitGroup) { ...@@ -45,6 +67,20 @@ func httpServer(wg *sync.WaitGroup) {
log.Fatal(s.Serve(ln)) log.Fatal(s.Serve(ln))
} }
func shadowServer(wg *sync.WaitGroup) {
defer wg.Done()
s := &gost.Server{}
s.Handle(gost.ShadowHandler(
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
))
ln, err := gost.TCPListener(":8338")
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
func tlsServer(wg *sync.WaitGroup) { func tlsServer(wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
...@@ -95,17 +131,3 @@ func wssServer(wg *sync.WaitGroup) { ...@@ -95,17 +131,3 @@ func wssServer(wg *sync.WaitGroup) {
} }
log.Fatal(s.Serve(ln)) log.Fatal(s.Serve(ln))
} }
func shadowServer(wg *sync.WaitGroup) {
defer wg.Done()
s := &gost.Server{}
s.Handle(gost.ShadowHandler(
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
))
ln, err := gost.TCPListener(":8338")
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
package tcp
import (
"net"
"github.com/ginuerzh/gost"
"github.com/ginuerzh/gost/server"
)
type nodeServer struct {
options *server.Server
}
func (s *nodeServer) Init(opts ...server.Option) {
for _, opt := range opts {
opt(s.options)
}
}
func (s *nodeServer) Options() *server.Options {
return s.options
}
func (s *nodeServer) Run() error {
ln, err := net.Listen("tcp", s.options.Addr)
if err != nil {
return err
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
return err
}
go func(c net.Conn) {
defer c.Close()
gost.DefaultHandler(s).Handle(conn)
}(conn)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment