add SSH remote forward support
This commit is contained in:
parent
151a2f902b
commit
f9f16d74a9
@ -16,14 +16,6 @@ type Client struct {
|
|||||||
Transporter Transporter
|
Transporter Transporter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a proxy client.
|
|
||||||
func NewClient(c Connector, tr Transporter) *Client {
|
|
||||||
return &Client{
|
|
||||||
Connector: c,
|
|
||||||
Transporter: tr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dial connects to the target address.
|
// Dial connects to the target address.
|
||||||
func (c *Client) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
func (c *Client) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return c.Transporter.Dial(addr, options...)
|
return c.Transporter.Dial(addr, options...)
|
||||||
@ -40,7 +32,7 @@ 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 = &Client{Connector: HTTPConnector(nil), Transporter: TCPTransporter()}
|
||||||
|
|
||||||
// Dial connects to the address addr via the DefaultClient.
|
// Dial connects to the address addr via the DefaultClient.
|
||||||
func Dial(addr string, options ...DialOption) (net.Conn, error) {
|
func Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
@ -174,3 +166,9 @@ func KCPConfigHandshakeOption(config *KCPConfig) HandshakeOption {
|
|||||||
opts.KCPConfig = config
|
opts.KCPConfig = config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func QUICConfigHandshakeOption(config *QUICConfig) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.QUICConfig = config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -142,10 +142,10 @@ func main() {
|
|||||||
// http+quic
|
// http+quic
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "localhost:6121",
|
Addr: "localhost:6121",
|
||||||
Client: gost.NewClient(
|
Client: &gost.Client{
|
||||||
gost.HTTPConnector(url.UserPassword("admin", "123456")),
|
Connector: gost.HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
gost.QUICTransporter(nil),
|
Transporter: gost.QUICTransporter(nil),
|
||||||
),
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ func main() {
|
|||||||
// go rtcpForwardServer()
|
// go rtcpForwardServer()
|
||||||
// go rudpForwardServer()
|
// go rudpForwardServer()
|
||||||
// go tcpRedirectServer()
|
// go tcpRedirectServer()
|
||||||
// go sshForwardServer()
|
|
||||||
go sshTunnelServer()
|
go sshTunnelServer()
|
||||||
// go http2Server()
|
// go http2Server()
|
||||||
go quicServer()
|
go quicServer()
|
||||||
@ -46,100 +45,99 @@ func main() {
|
|||||||
|
|
||||||
func httpServer() {
|
func httpServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.TCPListener(":18080")
|
ln, err := gost.TCPListener(":18080")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func socks5Server() {
|
func socks5Server() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.SOCKS5Handler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
gost.TLSConfigHandlerOption(tlsConfig()),
|
|
||||||
))
|
|
||||||
ln, err := gost.TCPListener(":11080")
|
ln, err := gost.TCPListener(":11080")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.SOCKS5Handler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
gost.TLSConfigHandlerOption(tlsConfig()),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func shadowServer() {
|
func shadowServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.ShadowHandler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.TCPListener(":18338")
|
ln, err := gost.TCPListener(":18338")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.ShadowHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func tlsServer() {
|
func tlsServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.TLSListener(":11443", tlsConfig())
|
ln, err := gost.TLSListener(":11443", tlsConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsServer() {
|
func wsServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.WSListener(":18000", nil)
|
ln, err := gost.WSListener(":18000", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func wssServer() {
|
func wssServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
ln, err := gost.WSSListener(":18443", tlsConfig(), nil)
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.WSSListener(":18443", &gost.WSOptions{TLSConfig: tlsConfig()})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func kcpServer() {
|
func kcpServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler())
|
|
||||||
ln, err := gost.KCPListener(":18388", nil)
|
ln, err := gost.KCPListener(":18388", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler()
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func tcpForwardServer() {
|
func tcpForwardServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.TCPForwardHandler("ginuerzh.xyz:22"))
|
|
||||||
ln, err := gost.TCPListener(":2222")
|
ln, err := gost.TCPListener(":2222")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.TCPForwardHandler("localhost:22")
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func rtcpForwardServer() {
|
func rtcpForwardServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.RTCPForwardHandler(":1222", "ginuerzh.xyz:22"))
|
|
||||||
ln, err := gost.RTCPForwardListener(
|
ln, err := gost.RTCPForwardListener(
|
||||||
":1222",
|
":1222",
|
||||||
gost.NewChain(
|
gost.NewChain(
|
||||||
@ -148,22 +146,22 @@ func rtcpForwardServer() {
|
|||||||
Transport: "tcp",
|
Transport: "tcp",
|
||||||
Addr: "localhost:12345",
|
Addr: "localhost:12345",
|
||||||
User: url.UserPassword("admin", "123456"),
|
User: url.UserPassword("admin", "123456"),
|
||||||
Client: gost.NewClient(
|
Client: &gost.Client{
|
||||||
gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
gost.TCPTransporter(),
|
Transporter: gost.TCPTransporter(),
|
||||||
),
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal()
|
log.Fatal()
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.RTCPForwardHandler(":1222", "localhost:22")
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func rudpForwardServer() {
|
func rudpForwardServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.RUDPForwardHandler(":10053", "localhost:53"))
|
|
||||||
ln, err := gost.RUDPForwardListener(
|
ln, err := gost.RUDPForwardListener(
|
||||||
":10053",
|
":10053",
|
||||||
gost.NewChain(
|
gost.NewChain(
|
||||||
@ -172,86 +170,67 @@ func rudpForwardServer() {
|
|||||||
Transport: "tcp",
|
Transport: "tcp",
|
||||||
Addr: "localhost:12345",
|
Addr: "localhost:12345",
|
||||||
User: url.UserPassword("admin", "123456"),
|
User: url.UserPassword("admin", "123456"),
|
||||||
Client: gost.NewClient(
|
Client: &gost.Client{
|
||||||
gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
gost.TCPTransporter(),
|
Transporter: gost.TCPTransporter(),
|
||||||
),
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal()
|
log.Fatal()
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.RUDPForwardHandler(":10053", "localhost:53")
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func tcpRedirectServer() {
|
func tcpRedirectServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.TCPRedirectHandler())
|
|
||||||
ln, err := gost.TCPListener(":8008")
|
ln, err := gost.TCPListener(":8008")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.TCPRedirectHandler()
|
||||||
}
|
log.Fatal(s.Serve(ln, h))
|
||||||
|
|
||||||
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() {
|
func sshTunnelServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(
|
|
||||||
gost.HTTPHandler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
ln, err := gost.SSHTunnelListener(":12222", &gost.SSHConfig{TLSConfig: tlsConfig()})
|
ln, err := gost.SSHTunnelListener(":12222", &gost.SSHConfig{TLSConfig: tlsConfig()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func http2Server() {
|
func http2Server() {
|
||||||
// http2.VerboseLogs = true
|
// http2.VerboseLogs = true
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTP2Handler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.TLSListener(":1443", tlsConfig()) // HTTP2 h2 mode
|
ln, err := gost.TLSListener(":1443", tlsConfig()) // HTTP2 h2 mode
|
||||||
// ln, err := gost.TCPListener(":1443") // HTTP2 h2c mode
|
// ln, err := gost.TCPListener(":1443") // HTTP2 h2c mode
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTP2Handler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
func quicServer() {
|
func quicServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler(
|
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
|
||||||
))
|
|
||||||
ln, err := gost.QUICListener("localhost:6121", &gost.QUICConfig{TLSConfig: tlsConfig()})
|
ln, err := gost.QUICListener("localhost:6121", &gost.QUICConfig{TLSConfig: tlsConfig()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.HTTPHandler(
|
||||||
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
34
gost/examples/forward/direct/client.go
Normal file
34
gost/examples/forward/direct/client.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gost/gost"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
tcpForward()
|
||||||
|
}
|
||||||
|
|
||||||
|
func tcpForward() {
|
||||||
|
chain := gost.NewChain(
|
||||||
|
gost.Node{
|
||||||
|
Addr: "localhost:11222",
|
||||||
|
Client: &gost.Client{
|
||||||
|
Connector: gost.SSHDirectForwardConnector(),
|
||||||
|
Transporter: gost.SSHForwardTransporter(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
s := &gost.Server{}
|
||||||
|
ln, err := gost.TCPListener(":11800")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
h := gost.TCPForwardHandler(
|
||||||
|
"localhost:22",
|
||||||
|
gost.ChainHandlerOption(chain),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
|
}
|
82
gost/examples/forward/direct/server.go
Normal file
82
gost/examples/forward/direct/server.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gost/gost"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sshForwardServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sshForwardServer() {
|
||||||
|
s := &gost.Server{}
|
||||||
|
ln, err := gost.TCPListener(":11222")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
h := gost.SSHForwardHandler(
|
||||||
|
gost.AddrHandlerOption(":11222"),
|
||||||
|
// gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
gost.TLSConfigHandlerOption(tlsConfig()),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
|
}
|
||||||
|
|
||||||
|
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}}
|
||||||
|
}
|
35
gost/examples/forward/remote/client.go
Normal file
35
gost/examples/forward/remote/client.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gost/gost"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sshRemoteForward()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sshRemoteForward() {
|
||||||
|
chain := gost.NewChain(
|
||||||
|
gost.Node{
|
||||||
|
Protocol: "forward",
|
||||||
|
Transport: "ssh",
|
||||||
|
Addr: "localhost:11222",
|
||||||
|
Client: &gost.Client{
|
||||||
|
Connector: gost.SSHRemoteForwardConnector(),
|
||||||
|
Transporter: gost.SSHForwardTransporter(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
s := &gost.Server{}
|
||||||
|
ln, err := gost.RTCPForwardListener(":11800", chain)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
h := gost.RTCPForwardHandler(
|
||||||
|
"localhost:10000",
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
|
}
|
82
gost/examples/forward/remote/server.go
Normal file
82
gost/examples/forward/remote/server.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gost/gost"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sshRemoteForwardServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func sshRemoteForwardServer() {
|
||||||
|
s := &gost.Server{}
|
||||||
|
ln, err := gost.TCPListener(":11222")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
h := gost.SSHForwardHandler(
|
||||||
|
gost.AddrHandlerOption(":11222"),
|
||||||
|
// gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
|
gost.TLSConfigHandlerOption(tlsConfig()),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
|
}
|
||||||
|
|
||||||
|
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}}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ginuerzh/gost/gost"
|
"github.com/ginuerzh/gost/gost"
|
||||||
)
|
)
|
||||||
@ -17,7 +18,7 @@ func init() {
|
|||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
|
||||||
flag.StringVar(&laddr, "L", ":18080", "listen address")
|
flag.StringVar(&laddr, "L", ":18080", "listen address")
|
||||||
flag.StringVar(&faddr, "F", ":6121", "forward address")
|
flag.StringVar(&faddr, "F", "localhost:6121", "forward address")
|
||||||
flag.BoolVar(&quiet, "q", false, "quiet mode")
|
flag.BoolVar(&quiet, "q", false, "quiet mode")
|
||||||
flag.BoolVar(&gost.Debug, "d", false, "debug mode")
|
flag.BoolVar(&gost.Debug, "d", false, "debug mode")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -33,23 +34,23 @@ func main() {
|
|||||||
Protocol: "socks5",
|
Protocol: "socks5",
|
||||||
Transport: "quic",
|
Transport: "quic",
|
||||||
Addr: faddr,
|
Addr: faddr,
|
||||||
Client: gost.NewClient(
|
Client: &gost.Client{
|
||||||
gost.SOCKS5Connector(nil),
|
Connector: gost.SOCKS5Connector(nil),
|
||||||
gost.QUICTransporter(nil),
|
Transporter: gost.QUICTransporter(&gost.QUICConfig{Timeout: 30 * time.Second, KeepAlive: true}),
|
||||||
),
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.SOCKS5Handler(
|
|
||||||
gost.ChainHandlerOption(chain),
|
|
||||||
gost.TLSConfigHandlerOption(tlsConfig()),
|
|
||||||
))
|
|
||||||
ln, err := gost.TCPListener(laddr)
|
ln, err := gost.TCPListener(laddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.SOCKS5Handler(
|
||||||
|
gost.ChainHandlerOption(chain),
|
||||||
|
gost.TLSConfigHandlerOption(tlsConfig()),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -33,16 +33,13 @@ func main() {
|
|||||||
|
|
||||||
func quicServer() {
|
func quicServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(
|
|
||||||
gost.SOCKS5Handler(gost.TLSConfigHandlerOption(tlsConfig())),
|
|
||||||
)
|
|
||||||
|
|
||||||
ln, err := gost.QUICListener(laddr, &gost.QUICConfig{TLSConfig: tlsConfig()})
|
ln, err := gost.QUICListener(laddr, &gost.QUICConfig{TLSConfig: tlsConfig()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
h := gost.SOCKS5Handler(gost.TLSConfigHandlerOption(tlsConfig()))
|
||||||
log.Println("server listen on", laddr)
|
log.Println("server listen on", laddr)
|
||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -33,23 +33,23 @@ func main() {
|
|||||||
Protocol: "socks5",
|
Protocol: "socks5",
|
||||||
Transport: "ssh",
|
Transport: "ssh",
|
||||||
Addr: faddr,
|
Addr: faddr,
|
||||||
Client: gost.NewClient(
|
Client: &gost.Client{
|
||||||
gost.SOCKS5Connector(nil),
|
Connector: gost.SOCKS5Connector(nil),
|
||||||
gost.SSHTunnelTransporter(),
|
Transporter: gost.SSHTunnelTransporter(),
|
||||||
),
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.SOCKS5Handler(
|
|
||||||
gost.ChainHandlerOption(chain),
|
|
||||||
gost.TLSConfigHandlerOption(tlsConfig()),
|
|
||||||
))
|
|
||||||
ln, err := gost.TCPListener(laddr)
|
ln, err := gost.TCPListener(laddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Fatal(s.Serve(ln))
|
h := gost.SOCKS5Handler(
|
||||||
|
gost.ChainHandlerOption(chain),
|
||||||
|
gost.TLSConfigHandlerOption(tlsConfig()),
|
||||||
|
)
|
||||||
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -33,16 +33,13 @@ func main() {
|
|||||||
|
|
||||||
func sshTunnelServer() {
|
func sshTunnelServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(
|
|
||||||
gost.SOCKS5Handler(gost.TLSConfigHandlerOption(tlsConfig())),
|
|
||||||
)
|
|
||||||
|
|
||||||
ln, err := gost.SSHTunnelListener(laddr, &gost.SSHConfig{TLSConfig: tlsConfig()})
|
ln, err := gost.SSHTunnelListener(laddr, &gost.SSHConfig{TLSConfig: tlsConfig()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
h := gost.SOCKS5Handler(gost.TLSConfigHandlerOption(tlsConfig()))
|
||||||
log.Println("server listen on", laddr)
|
log.Println("server listen on", laddr)
|
||||||
log.Fatal(s.Serve(ln))
|
log.Fatal(s.Serve(ln, h))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -74,16 +74,14 @@ func (h *udpForwardHandler) Handle(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type rtcpForwardHandler struct {
|
type rtcpForwardHandler struct {
|
||||||
laddr string
|
|
||||||
raddr string
|
raddr string
|
||||||
options *HandlerOptions
|
options *HandlerOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// RTCPForwardHandler creates a server Handler for TCP remote port forwarding server.
|
// RTCPForwardHandler creates a server Handler for TCP remote port forwarding server.
|
||||||
// The raddr is the remote address that the server will forward to.
|
// The raddr is the remote address that the server will forward to.
|
||||||
func RTCPForwardHandler(laddr, raddr string, opts ...HandlerOption) Handler {
|
func RTCPForwardHandler(raddr string, opts ...HandlerOption) Handler {
|
||||||
h := &rtcpForwardHandler{
|
h := &rtcpForwardHandler{
|
||||||
laddr: laddr,
|
|
||||||
raddr: raddr,
|
raddr: raddr,
|
||||||
options: &HandlerOptions{},
|
options: &HandlerOptions{},
|
||||||
}
|
}
|
||||||
@ -98,14 +96,14 @@ func (h *rtcpForwardHandler) Handle(conn net.Conn) {
|
|||||||
|
|
||||||
cc, err := net.DialTimeout("tcp", h.raddr, DialTimeout)
|
cc, err := net.DialTimeout("tcp", h.raddr, DialTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[rtcp] %s -> %s : %s", h.laddr, h.raddr, err)
|
log.Logf("[rtcp] %s -> %s : %s", conn.LocalAddr(), h.raddr, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer cc.Close()
|
defer cc.Close()
|
||||||
|
|
||||||
log.Logf("[rtcp] %s <-> %s", h.laddr, h.raddr)
|
log.Logf("[rtcp] %s <-> %s", conn.LocalAddr(), h.raddr)
|
||||||
transport(cc, conn)
|
transport(cc, conn)
|
||||||
log.Logf("[rtcp] %s >-< %s", h.laddr, h.raddr)
|
log.Logf("[rtcp] %s >-< %s", conn.LocalAddr(), h.raddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
type rudpForwardHandler struct {
|
type rudpForwardHandler struct {
|
||||||
@ -217,9 +215,9 @@ func (l *udpForwardListener) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type rtcpForwardListener struct {
|
type rtcpForwardListener struct {
|
||||||
addr net.Addr
|
addr net.Addr
|
||||||
chain *Chain
|
chain *Chain
|
||||||
close chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RTCPForwardListener creates a Listener for TCP remote port forwarding server.
|
// RTCPForwardListener creates a Listener for TCP remote port forwarding server.
|
||||||
@ -230,33 +228,59 @@ func RTCPForwardListener(addr string, chain *Chain) (Listener, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &rtcpForwardListener{
|
return &rtcpForwardListener{
|
||||||
addr: laddr,
|
addr: laddr,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
close: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *rtcpForwardListener) Accept() (net.Conn, error) {
|
func (l *rtcpForwardListener) Accept() (net.Conn, error) {
|
||||||
select {
|
select {
|
||||||
case <-l.close:
|
case <-l.closed:
|
||||||
return nil, errors.New("closed")
|
return nil, errors.New("closed")
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := l.chain.Conn()
|
var tempDelay time.Duration
|
||||||
if err != nil {
|
for {
|
||||||
return nil, err
|
conn, err := l.accept()
|
||||||
|
if err != nil {
|
||||||
|
if tempDelay == 0 {
|
||||||
|
tempDelay = 1000 * time.Millisecond
|
||||||
|
} else {
|
||||||
|
tempDelay *= 2
|
||||||
|
}
|
||||||
|
if max := 6 * time.Second; tempDelay > max {
|
||||||
|
tempDelay = max
|
||||||
|
}
|
||||||
|
log.Logf("[ssh-rtcp] Accept error: %v; retrying in %v", err, tempDelay)
|
||||||
|
time.Sleep(tempDelay)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
}
|
}
|
||||||
cc, err := l.handshake(conn)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cc, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *rtcpForwardListener) handshake(conn net.Conn) (net.Conn, error) {
|
func (l *rtcpForwardListener) accept() (conn net.Conn, err error) {
|
||||||
|
lastNode := l.chain.LastNode()
|
||||||
|
if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" {
|
||||||
|
conn, err = l.chain.Dial(l.addr.String())
|
||||||
|
} else if lastNode.Protocol == "socks5" {
|
||||||
|
cc, er := l.chain.Conn()
|
||||||
|
if er != nil {
|
||||||
|
return nil, er
|
||||||
|
}
|
||||||
|
conn, err = l.waitConnectSOCKS5(cc)
|
||||||
|
if err != nil {
|
||||||
|
cc.Close()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = errors.New("invalid chain")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *rtcpForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
|
||||||
conn, err := socks5Handshake(conn, l.chain.LastNode().User)
|
conn, err := socks5Handshake(conn, l.chain.LastNode().User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -301,7 +325,7 @@ func (l *rtcpForwardListener) Addr() net.Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *rtcpForwardListener) Close() error {
|
func (l *rtcpForwardListener) Close() error {
|
||||||
close(l.close)
|
close(l.closed)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ type Node struct {
|
|||||||
Addr string
|
Addr string
|
||||||
Protocol string
|
Protocol string
|
||||||
Transport string
|
Transport string
|
||||||
User *url.Userinfo
|
User *url.Userinfo
|
||||||
Client *Client
|
Client *Client
|
||||||
|
Server *Server
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,23 @@ import (
|
|||||||
|
|
||||||
// Server is a proxy server.
|
// Server is a proxy server.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
l net.Listener
|
|
||||||
handler Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle sets a handler for the server.
|
|
||||||
func (s *Server) Handle(h Handler) {
|
|
||||||
s.handler = h
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve serves as a proxy server.
|
// Serve serves as a proxy server.
|
||||||
func (s *Server) Serve(l net.Listener) error {
|
func (s *Server) Serve(l net.Listener, h Handler) error {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
|
if l == nil {
|
||||||
|
ln, err := TCPListener(":8080")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l = ln
|
||||||
|
}
|
||||||
|
if h == nil {
|
||||||
|
h = HTTPHandler()
|
||||||
|
}
|
||||||
|
|
||||||
var tempDelay time.Duration
|
var tempDelay time.Duration
|
||||||
for {
|
for {
|
||||||
conn, e := l.Accept()
|
conn, e := l.Accept()
|
||||||
@ -43,7 +47,7 @@ func (s *Server) Serve(l net.Listener) error {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
tempDelay = 0
|
tempDelay = 0
|
||||||
go s.handler.Handle(conn)
|
go h.Handle(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
121
gost/ssh.go
121
gost/ssh.go
@ -9,6 +9,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -26,31 +27,88 @@ const (
|
|||||||
GostSSHTunnelRequest = "gost-tunnel" // extended request type for ssh tunnel
|
GostSSHTunnelRequest = "gost-tunnel" // extended request type for ssh tunnel
|
||||||
)
|
)
|
||||||
|
|
||||||
type sshForwardConnector struct {
|
type sshDirectForwardConnector struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SSHForwardConnector() Connector {
|
func SSHDirectForwardConnector() Connector {
|
||||||
return &sshForwardConnector{}
|
return &sshDirectForwardConnector{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sshForwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error) {
|
func (c *sshDirectForwardConnector) Connect(conn net.Conn, raddr string) (net.Conn, error) {
|
||||||
cc, ok := conn.(*sshNopConn)
|
cc, ok := conn.(*sshNopConn) // TODO: this is an ugly type assertion, need to find a better solution.
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("ssh: wrong connection type")
|
return nil, errors.New("ssh: wrong connection type")
|
||||||
}
|
}
|
||||||
conn, err := cc.session.client.Dial("tcp", addr)
|
conn, err := cc.session.client.Dial("tcp", raddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[ssh-tcp] %s -> %s : %s", cc.session.addr, addr, err)
|
log.Logf("[ssh-tcp] %s -> %s : %s", cc.session.addr, raddr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sshRemoteForwardConnector struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func SSHRemoteForwardConnector() Connector {
|
||||||
|
return &sshRemoteForwardConnector{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sshRemoteForwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error) {
|
||||||
|
cc, ok := conn.(*sshNopConn) // TODO: this is an ugly type assertion, need to find a better solution.
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("ssh: wrong connection type")
|
||||||
|
}
|
||||||
|
|
||||||
|
cc.session.once.Do(func() {
|
||||||
|
go func() {
|
||||||
|
defer log.Log("ssh-rtcp: session is closed")
|
||||||
|
defer close(cc.session.connChan)
|
||||||
|
|
||||||
|
if cc.session == nil || cc.session.client == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(addr, ":") {
|
||||||
|
addr = "0.0.0.0" + addr
|
||||||
|
}
|
||||||
|
ln, err := cc.session.client.Listen("tcp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
rc, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Logf("[ssh-rtcp] %s <-> %s accpet : %s", ln.Addr(), addr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case cc.session.connChan <- rc:
|
||||||
|
default:
|
||||||
|
log.Logf("[ssh-rtcp] %s - %s: connection queue is full", ln.Addr(), addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
|
||||||
|
sc, ok := <-cc.session.connChan
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("ssh-rtcp: connection is closed")
|
||||||
|
}
|
||||||
|
return sc, nil
|
||||||
|
}
|
||||||
|
|
||||||
type sshForwardTransporter struct {
|
type sshForwardTransporter struct {
|
||||||
sessions map[string]*sshSession
|
sessions map[string]*sshSession
|
||||||
sessionMutex sync.Mutex
|
sessionMutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SSHForwardTransporter() Transporter {
|
||||||
|
return &sshForwardTransporter{
|
||||||
|
sessions: make(map[string]*sshSession),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (tr *sshForwardTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
|
func (tr *sshForwardTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
|
||||||
opts := &DialOptions{}
|
opts := &DialOptions{}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
@ -61,7 +119,7 @@ func (tr *sshForwardTransporter) Dial(addr string, options ...DialOption) (conn
|
|||||||
defer tr.sessionMutex.Unlock()
|
defer tr.sessionMutex.Unlock()
|
||||||
|
|
||||||
session, ok := tr.sessions[addr]
|
session, ok := tr.sessions[addr]
|
||||||
if !ok {
|
if !ok || session.Closed() {
|
||||||
if opts.Chain == nil {
|
if opts.Chain == nil {
|
||||||
conn, err = net.DialTimeout("tcp", addr, opts.Timeout)
|
conn, err = net.DialTimeout("tcp", addr, opts.Timeout)
|
||||||
} else {
|
} else {
|
||||||
@ -87,7 +145,8 @@ func (tr *sshForwardTransporter) Handshake(conn net.Conn, options ...HandshakeOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := ssh.ClientConfig{
|
config := ssh.ClientConfig{
|
||||||
Timeout: opts.Timeout,
|
Timeout: opts.Timeout,
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
if opts.User != nil {
|
if opts.User != nil {
|
||||||
config.User = opts.User.Username()
|
config.User = opts.User.Username()
|
||||||
@ -101,6 +160,10 @@ func (tr *sshForwardTransporter) Handshake(conn net.Conn, options ...HandshakeOp
|
|||||||
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("ssh: unrecognized connection")
|
||||||
|
}
|
||||||
if !ok || session.client == nil {
|
if !ok || session.client == nil {
|
||||||
sshConn, chans, reqs, err := ssh.NewClientConn(conn, opts.Addr, &config)
|
sshConn, chans, reqs, err := ssh.NewClientConn(conn, opts.Addr, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,13 +173,23 @@ func (tr *sshForwardTransporter) Handshake(conn net.Conn, options ...HandshakeOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
session = &sshSession{
|
session = &sshSession{
|
||||||
addr: opts.Addr,
|
addr: opts.Addr,
|
||||||
conn: conn,
|
conn: conn,
|
||||||
client: ssh.NewClient(sshConn, chans, reqs),
|
client: ssh.NewClient(sshConn, chans, reqs),
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
|
deaded: make(chan struct{}),
|
||||||
|
connChan: make(chan net.Conn, 1024),
|
||||||
}
|
}
|
||||||
tr.sessions[opts.Addr] = session
|
tr.sessions[opts.Addr] = session
|
||||||
|
go session.Ping(opts.Interval, 1)
|
||||||
|
go session.waitServer()
|
||||||
|
go session.waitClose()
|
||||||
}
|
}
|
||||||
|
if session.Closed() {
|
||||||
|
delete(tr.sessions, opts.Addr)
|
||||||
|
return nil, ErrSessionDead
|
||||||
|
}
|
||||||
|
|
||||||
return &sshNopConn{session: session}, nil
|
return &sshNopConn{session: session}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,11 +303,13 @@ func (tr *sshTunnelTransporter) Multiplex() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sshSession struct {
|
type sshSession struct {
|
||||||
addr string
|
addr string
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
client *ssh.Client
|
client *ssh.Client
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
deaded chan struct{}
|
deaded chan struct{}
|
||||||
|
once sync.Once
|
||||||
|
connChan chan net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sshSession) Ping(interval time.Duration, retries int) {
|
func (s *sshSession) Ping(interval time.Duration, retries int) {
|
||||||
@ -334,7 +409,7 @@ func SSHForwardHandler(opts ...HandlerOption) Handler {
|
|||||||
if h.options.TLSConfig != nil && len(h.options.TLSConfig.Certificates) > 0 {
|
if h.options.TLSConfig != nil && len(h.options.TLSConfig.Certificates) > 0 {
|
||||||
signer, err := ssh.NewSignerFromKey(h.options.TLSConfig.Certificates[0].PrivateKey)
|
signer, err := ssh.NewSignerFromKey(h.options.TLSConfig.Certificates[0].PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log("[sshf]", err)
|
log.Log("[ssh-forward]", err)
|
||||||
}
|
}
|
||||||
h.config.AddHostKey(signer)
|
h.config.AddHostKey(signer)
|
||||||
}
|
}
|
||||||
@ -345,15 +420,15 @@ func SSHForwardHandler(opts ...HandlerOption) Handler {
|
|||||||
func (h *sshForwardHandler) Handle(conn net.Conn) {
|
func (h *sshForwardHandler) Handle(conn net.Conn) {
|
||||||
sshConn, chans, reqs, err := ssh.NewServerConn(conn, h.config)
|
sshConn, chans, reqs, err := ssh.NewServerConn(conn, h.config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Logf("[sshf] %s -> %s : %s", conn.RemoteAddr(), h.options.Addr, err)
|
log.Logf("[ssh-forward] %s -> %s : %s", conn.RemoteAddr(), h.options.Addr, err)
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer sshConn.Close()
|
defer sshConn.Close()
|
||||||
|
|
||||||
log.Logf("[sshf] %s <-> %s", conn.RemoteAddr(), h.options.Addr)
|
log.Logf("[ssh-forward] %s <-> %s", conn.RemoteAddr(), h.options.Addr)
|
||||||
h.handleForward(sshConn, chans, reqs)
|
h.handleForward(sshConn, chans, reqs)
|
||||||
log.Logf("[sshf] %s >-< %s", conn.RemoteAddr(), h.options.Addr)
|
log.Logf("[ssh-forward] %s >-< %s", conn.RemoteAddr(), h.options.Addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *sshForwardHandler) handleForward(conn ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) {
|
func (h *sshForwardHandler) handleForward(conn ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) {
|
||||||
@ -366,7 +441,7 @@ func (h *sshForwardHandler) handleForward(conn ssh.Conn, chans <-chan ssh.NewCha
|
|||||||
case RemoteForwardRequest:
|
case RemoteForwardRequest:
|
||||||
go h.tcpipForwardRequest(conn, req, quit)
|
go h.tcpipForwardRequest(conn, req, quit)
|
||||||
default:
|
default:
|
||||||
log.Log("[ssh] unknown channel type:", req.Type)
|
// log.Log("[ssh] unknown channel type:", req.Type)
|
||||||
if req.WantReply {
|
if req.WantReply {
|
||||||
req.Reply(false, nil)
|
req.Reply(false, nil)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ type WSOptions struct {
|
|||||||
WriteBufferSize int
|
WriteBufferSize int
|
||||||
HandshakeTimeout time.Duration
|
HandshakeTimeout time.Duration
|
||||||
EnableCompression bool
|
EnableCompression bool
|
||||||
TLSConfig *tls.Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketConn struct {
|
type websocketConn struct {
|
||||||
@ -243,7 +242,7 @@ type wssListener struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WSSListener creates a Listener for websocket secure proxy server.
|
// WSSListener creates a Listener for websocket secure proxy server.
|
||||||
func WSSListener(addr string, options *WSOptions) (Listener, error) {
|
func WSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Listener, error) {
|
||||||
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
|
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -269,7 +268,7 @@ func WSSListener(addr string, options *WSOptions) (Listener, error) {
|
|||||||
mux.Handle("/ws", http.HandlerFunc(l.upgrade))
|
mux.Handle("/ws", http.HandlerFunc(l.upgrade))
|
||||||
l.srv = &http.Server{
|
l.srv = &http.Server{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
TLSConfig: options.TLSConfig,
|
TLSConfig: tlsConfig,
|
||||||
Handler: mux,
|
Handler: mux,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +278,7 @@ func WSSListener(addr string, options *WSOptions) (Listener, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := l.srv.Serve(tls.NewListener(tcpKeepAliveListener{ln}, options.TLSConfig))
|
err := l.srv.Serve(tls.NewListener(tcpKeepAliveListener{ln}, tlsConfig))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.errChan <- err
|
l.errChan <- err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user