Commit 302476f4 authored by rui.zheng's avatar rui.zheng

add ssh tunnel support

parent cb7cc4aa
...@@ -3,6 +3,7 @@ package gost ...@@ -3,6 +3,7 @@ package gost
import ( import (
"crypto/tls" "crypto/tls"
"net" "net"
"net/url"
"time" "time"
) )
...@@ -120,7 +121,9 @@ func ChainDialOption(chain *Chain) DialOption { ...@@ -120,7 +121,9 @@ func ChainDialOption(chain *Chain) DialOption {
// HandshakeOptions describes the options for handshake. // HandshakeOptions describes the options for handshake.
type HandshakeOptions struct { type HandshakeOptions struct {
Addr string Addr string
User *url.Userinfo
Timeout time.Duration Timeout time.Duration
Interval time.Duration
TLSConfig *tls.Config TLSConfig *tls.Config
WSOptions *WSOptions WSOptions *WSOptions
KCPConfig *KCPConfig KCPConfig *KCPConfig
...@@ -135,12 +138,24 @@ func AddrHandshakeOption(addr string) HandshakeOption { ...@@ -135,12 +138,24 @@ func AddrHandshakeOption(addr string) HandshakeOption {
} }
} }
func UserHandshakeOption(user *url.Userinfo) HandshakeOption {
return func(opts *HandshakeOptions) {
opts.User = user
}
}
func TimeoutHandshakeOption(timeout time.Duration) HandshakeOption { func TimeoutHandshakeOption(timeout time.Duration) HandshakeOption {
return func(opts *HandshakeOptions) { return func(opts *HandshakeOptions) {
opts.Timeout = timeout opts.Timeout = timeout
} }
} }
func IntervalHandshakeOption(interval time.Duration) HandshakeOption {
return func(opts *HandshakeOptions) {
opts.Interval = interval
}
}
func TLSConfigHandshakeOption(config *tls.Config) HandshakeOption { func TLSConfigHandshakeOption(config *tls.Config) HandshakeOption {
return func(opts *HandshakeOptions) { return func(opts *HandshakeOptions) {
opts.TLSConfig = config opts.TLSConfig = config
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"log" "log"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url"
"sync" "sync"
"time" "time"
...@@ -116,12 +117,23 @@ func main() { ...@@ -116,12 +117,23 @@ func main() {
}, },
*/ */
// http+kcp /*
// http+kcp
gost.Node{
Addr: "127.0.0.1:18388",
Client: gost.NewClient(
gost.HTTPConnector(nil),
gost.KCPTransporter(nil),
),
},
*/
// http+ssh
gost.Node{ gost.Node{
Addr: "127.0.0.1:18388", Addr: "127.0.0.1:12222",
Client: gost.NewClient( Client: gost.NewClient(
gost.HTTPConnector(nil), gost.HTTPConnector(url.UserPassword("admin", "123456")),
gost.KCPTransporter(nil), gost.SSHTunnelTransporter(),
), ),
}, },
) )
...@@ -143,6 +155,7 @@ func main() { ...@@ -143,6 +155,7 @@ func main() {
duration := time.Since(start) duration := time.Since(start)
total += concurrency total += concurrency
log.Printf("%d/%d/%d requests done (%v/%v)", total, requests, concurrency, duration, duration/time.Duration(concurrency)) log.Printf("%d/%d/%d requests done (%v/%v)", total, requests, concurrency, duration, duration/time.Duration(concurrency))
time.Sleep(500 * time.Millisecond)
} }
} }
......
...@@ -37,6 +37,8 @@ func main() { ...@@ -37,6 +37,8 @@ func main() {
// go rtcpForwardServer() // go rtcpForwardServer()
// go rudpForwardServer() // go rudpForwardServer()
// go tcpRedirectServer() // go tcpRedirectServer()
// go sshForwardServer()
go sshTunnelServer()
// go http2Server() // go http2Server()
select {} select {}
...@@ -193,6 +195,38 @@ func tcpRedirectServer() { ...@@ -193,6 +195,38 @@ func tcpRedirectServer() {
log.Fatal(s.Serve(ln)) log.Fatal(s.Serve(ln))
} }
func sshForwardServer() {
s := &gost.Server{}
s.Handle(
gost.SSHForwardHandler(
gost.AddrHandlerOption(":1222"),
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
gost.TLSConfigHandlerOption(tlsConfig()),
),
)
ln, err := gost.TCPListener(":1222")
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
func sshTunnelServer() {
s := &gost.Server{}
s.Handle(
gost.HTTPHandler(
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
),
)
ln, err := gost.SSHTunnelListener(":12222", &gost.SSHConfig{TLSConfig: tlsConfig()})
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
func http2Server() { func http2Server() {
// http2.VerboseLogs = true // http2.VerboseLogs = true
......
package main
import (
"flag"
"log"
"github.com/ginuerzh/gost/gost"
)
var (
laddr, faddr string
quiet bool
)
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
flag.StringVar(&laddr, "L", ":18080", "listen address")
flag.StringVar(&faddr, "F", ":12222", "forward address")
flag.BoolVar(&quiet, "q", false, "quiet mode")
flag.BoolVar(&gost.Debug, "d", false, "debug mode")
flag.Parse()
if quiet {
gost.SetLogger(&gost.NopLogger{})
}
}
func main() {
chain := gost.NewChain(
gost.Node{
Addr: faddr,
Client: gost.NewClient(
gost.HTTPConnector(nil),
gost.SSHTunnelTransporter(),
),
},
)
s := &gost.Server{}
s.Handle(gost.HTTPHandler(gost.ChainHandlerOption(chain)))
ln, err := gost.TCPListener(laddr)
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
package main
import (
"crypto/tls"
"flag"
"log"
"github.com/ginuerzh/gost/gost"
)
var (
laddr string
quiet bool
)
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
flag.StringVar(&laddr, "L", ":12222", "listen address")
flag.BoolVar(&quiet, "q", false, "quiet mode")
flag.BoolVar(&gost.Debug, "d", false, "debug mode")
flag.Parse()
if quiet {
gost.SetLogger(&gost.NopLogger{})
}
}
func main() {
sshTunnelServer()
}
func sshTunnelServer() {
s := &gost.Server{}
s.Handle(
gost.HTTPHandler(),
)
ln, err := gost.SSHTunnelListener(laddr, &gost.SSHConfig{TLSConfig: tlsConfig()})
if err != nil {
log.Fatal(err)
}
log.Fatal(s.Serve(ln))
}
var (
rawCert = []byte(`-----BEGIN CERTIFICATE-----
MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
-----END CERTIFICATE-----`)
rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
-----END RSA PRIVATE KEY-----`)
)
func tlsConfig() *tls.Config {
cert, err := tls.X509KeyPair(rawCert, rawKey)
if err != nil {
panic(err)
}
return &tls.Config{Certificates: []tls.Certificate{cert}}
}
...@@ -13,6 +13,7 @@ type Handler interface { ...@@ -13,6 +13,7 @@ type Handler interface {
// HandlerOptions describes the options for Handler. // HandlerOptions describes the options for Handler.
type HandlerOptions struct { type HandlerOptions struct {
Addr string
Chain *Chain Chain *Chain
Users []*url.Userinfo Users []*url.Userinfo
TLSConfig *tls.Config TLSConfig *tls.Config
...@@ -21,6 +22,13 @@ type HandlerOptions struct { ...@@ -21,6 +22,13 @@ type HandlerOptions struct {
// HandlerOption allows a common way to set handler options. // HandlerOption allows a common way to set handler options.
type HandlerOption func(opts *HandlerOptions) 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. // ChainHandlerOption sets the Chain option of HandlerOptions.
func ChainHandlerOption(chain *Chain) HandlerOption { func ChainHandlerOption(chain *Chain) HandlerOption {
return func(opts *HandlerOptions) { return func(opts *HandlerOptions) {
......
...@@ -32,7 +32,7 @@ func HTTP2Connector(user *url.Userinfo) Connector { ...@@ -32,7 +32,7 @@ func HTTP2Connector(user *url.Userinfo) Connector {
func (c *http2Connector) Connect(conn net.Conn, addr string) (net.Conn, error) { func (c *http2Connector) Connect(conn net.Conn, addr string) (net.Conn, error) {
cc, ok := conn.(*http2DummyConn) cc, ok := conn.(*http2DummyConn)
if !ok { if !ok {
return nil, errors.New("conn must be a conn wrapper") return nil, errors.New("wrong connection type")
} }
pr, pw := io.Pipe() pr, pw := io.Pipe()
...@@ -155,10 +155,8 @@ type http2Handler struct { ...@@ -155,10 +155,8 @@ 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{
server: new(http2.Server), server: new(http2.Server),
options: &HandlerOptions{ options: new(HandlerOptions),
Chain: new(Chain),
},
} }
for _, opt := range opts { for _, opt := range opts {
opt(h.options) opt(h.options)
......
...@@ -214,10 +214,15 @@ func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) ( ...@@ -214,10 +214,15 @@ func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
defer tr.sessionMutex.Unlock() defer tr.sessionMutex.Unlock()
session, ok := tr.sessions[opts.Addr] session, ok := tr.sessions[opts.Addr]
if session != nil && session.conn != conn {
conn.Close()
return nil, errors.New("kcp: unrecognized connection")
}
if !ok || session.session == nil { if !ok || session.session == nil {
s, err := tr.initSession(opts.Addr, conn, config) s, err := tr.initSession(opts.Addr, conn, config)
if err != nil { if err != nil {
conn.Close() conn.Close()
delete(tr.sessions, opts.Addr)
return nil, err return nil, err
} }
session = s session = s
...@@ -236,7 +241,7 @@ func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) ( ...@@ -236,7 +241,7 @@ func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*kcpSession, error) { func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*kcpSession, error) {
udpConn, ok := conn.(*net.UDPConn) udpConn, ok := conn.(*net.UDPConn)
if !ok { if !ok {
return nil, errors.New("wrong connection type") return nil, errors.New("kcp: wrong connection type")
} }
kcpconn, err := kcp.NewConn(addr, kcpconn, err := kcp.NewConn(addr,
......
This diff is collapsed.
...@@ -26,10 +26,6 @@ func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) ( ...@@ -26,10 +26,6 @@ func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
return tls.Client(conn, opts.TLSConfig), nil return tls.Client(conn, opts.TLSConfig), nil
} }
func (tr *tlsTransporter) Multiplex() bool {
return false
}
type tlsListener struct { type tlsListener struct {
net.Listener net.Listener
} }
......
...@@ -122,10 +122,6 @@ func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (n ...@@ -122,10 +122,6 @@ func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (n
return websocketClientConn(url.String(), conn, nil, wsOptions) return websocketClientConn(url.String(), conn, nil, wsOptions)
} }
func (tr *wsTransporter) Multiplex() bool {
return false
}
type wssTransporter struct { type wssTransporter struct {
*tcpTransporter *tcpTransporter
options *WSOptions options *WSOptions
...@@ -154,10 +150,6 @@ func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) ( ...@@ -154,10 +150,6 @@ func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (
return websocketClientConn(url.String(), conn, opts.TLSConfig, wsOptions) return websocketClientConn(url.String(), conn, opts.TLSConfig, wsOptions)
} }
func (tr *wssTransporter) Multiplex() bool {
return false
}
type wsListener struct { type wsListener struct {
addr net.Addr addr net.Addr
upgrader *websocket.Upgrader upgrader *websocket.Upgrader
......
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