update examples
This commit is contained in:
parent
89d2b7b466
commit
dc0b4f5423
@ -78,12 +78,12 @@ func (c *Chain) Conn() (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nodes := c.nodes
|
nodes := c.nodes
|
||||||
conn, err := nodes[0].Client.Dial(nodes[0].Addr)
|
conn, err := nodes[0].Client.Dial(nodes[0].Addr, TimeoutDialOption(DialTimeout))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err = nodes[0].Client.Handshake(conn)
|
conn, err = nodes[0].Client.Handshake(conn, AddrHandshakeOption(nodes[0].Addr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ func (c *Chain) Conn() (net.Conn, error) {
|
|||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cc, err = next.Client.Handshake(cc)
|
cc, err = next.Client.Handshake(cc, AddrHandshakeOption(next.Addr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -2,28 +2,43 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
"net/url"
|
"sync"
|
||||||
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ginuerzh/gost/gost"
|
"github.com/ginuerzh/gost/gost"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
requests, concurrency int
|
||||||
|
quiet bool
|
||||||
|
swg, ewg sync.WaitGroup
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
gost.Debug = true
|
|
||||||
|
flag.IntVar(&requests, "n", 1, "Number of requests to perform")
|
||||||
|
flag.IntVar(&concurrency, "c", 1, "Number of multiple requests to make at a time")
|
||||||
|
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() {
|
func main() {
|
||||||
chain := gost.NewChain(
|
chain := gost.NewChain(
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// http+tcp
|
// http+tcp
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:8080",
|
Addr: "127.0.0.1:18080",
|
||||||
Client: gost.NewClient(
|
Client: gost.NewClient(
|
||||||
gost.HTTPConnector(url.UserPassword("admin", "123456")),
|
gost.HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
gost.TCPTransporter(),
|
gost.TCPTransporter(),
|
||||||
@ -34,7 +49,7 @@ func main() {
|
|||||||
/*
|
/*
|
||||||
// socks5+tcp
|
// socks5+tcp
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:1080",
|
Addr: "127.0.0.1:11080",
|
||||||
Client: gost.NewClient(
|
Client: gost.NewClient(
|
||||||
gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
|
||||||
gost.TCPTransporter(),
|
gost.TCPTransporter(),
|
||||||
@ -45,7 +60,7 @@ func main() {
|
|||||||
/*
|
/*
|
||||||
// ss+tcp
|
// ss+tcp
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:8338",
|
Addr: "127.0.0.1:18338",
|
||||||
Client: gost.NewClient(
|
Client: gost.NewClient(
|
||||||
gost.ShadowConnector(url.UserPassword("chacha20", "123456")),
|
gost.ShadowConnector(url.UserPassword("chacha20", "123456")),
|
||||||
gost.TCPTransporter(),
|
gost.TCPTransporter(),
|
||||||
@ -56,10 +71,10 @@ func main() {
|
|||||||
/*
|
/*
|
||||||
// http+ws
|
// http+ws
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:8000",
|
Addr: "127.0.0.1:18000",
|
||||||
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.WSTransporter(nil),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
@ -67,13 +82,10 @@ func main() {
|
|||||||
/*
|
/*
|
||||||
// http+wss
|
// http+wss
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:8443",
|
Addr: "127.0.0.1:18443",
|
||||||
Client: gost.NewClient(
|
Client: gost.NewClient(
|
||||||
gost.HTTPConnector(url.UserPassword("admin", "123456")),
|
gost.HTTPConnector(url.UserPassword("admin", "123456")),
|
||||||
gost.WSSTransporter(
|
gost.WSSTransporter(nil),
|
||||||
"127.0.0.1:8443",
|
|
||||||
&gost.WSOptions{TLSConfig: &tls.Config{InsecureSkipVerify: true}},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
@ -81,14 +93,15 @@ func main() {
|
|||||||
/*
|
/*
|
||||||
// http+tls
|
// http+tls
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:1443",
|
Addr: "127.0.0.1:11443",
|
||||||
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.TLSTransporter(),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
// http2+tls, http2+tcp
|
// http2+tls, http2+tcp
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:1443",
|
Addr: "127.0.0.1:1443",
|
||||||
@ -101,24 +114,49 @@ func main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
// http+kcp
|
// http+kcp
|
||||||
gost.Node{
|
gost.Node{
|
||||||
Addr: "127.0.0.1:8388",
|
Addr: "127.0.0.1:18388",
|
||||||
Client: gost.NewClient(
|
Client: gost.NewClient(
|
||||||
gost.HTTPConnector(nil),
|
gost.HTTPConnector(nil),
|
||||||
gost.KCPTransporter(nil),
|
gost.KCPTransporter(nil),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
total := 0
|
||||||
|
for total < requests {
|
||||||
|
startChan := make(chan struct{})
|
||||||
|
for i := 0; i < concurrency; i++ {
|
||||||
|
swg.Add(1)
|
||||||
|
ewg.Add(1)
|
||||||
|
go request(chain, startChan)
|
||||||
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
swg.Wait() // wait for workers ready
|
||||||
|
close(startChan) // start signal
|
||||||
|
ewg.Wait() // wait for workers done
|
||||||
|
|
||||||
|
duration := time.Since(start)
|
||||||
|
total += concurrency
|
||||||
|
log.Printf("%d/%d/%d requests done (%v/%v)", total, requests, concurrency, duration, duration/time.Duration(concurrency))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func request(chain *gost.Chain, start <-chan struct{}) {
|
||||||
|
defer ewg.Done()
|
||||||
|
|
||||||
|
swg.Done()
|
||||||
|
<-start
|
||||||
|
|
||||||
conn, err := chain.Dial("localhost:10000")
|
conn, err := chain.Dial("localhost:10000")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
//conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
|
//conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
|
||||||
req, err := http.NewRequest(http.MethodGet, "http://localhost:10000/pkg", nil)
|
req, err := http.NewRequest(http.MethodGet, "http://localhost:10000/pkg", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -133,11 +171,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if !quiet {
|
||||||
rb, _ := httputil.DumpRequest(req, true)
|
rb, _ := httputil.DumpRequest(req, true)
|
||||||
log.Println(string(rb))
|
log.Println(string(rb))
|
||||||
rb, _ = httputil.DumpResponse(resp, true)
|
rb, _ = httputil.DumpResponse(resp, true)
|
||||||
log.Println(string(rb))
|
log.Println(string(rb))
|
||||||
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package gost
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is a proxy client.
|
// Client is a proxy client.
|
||||||
@ -77,7 +78,14 @@ func TCPTransporter() Transporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tcpTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
func (tr *tcpTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
||||||
return net.Dial("tcp", addr)
|
opts := &DialOptions{}
|
||||||
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
if opts.Chain == nil {
|
||||||
|
return net.DialTimeout("tcp", addr, opts.Timeout)
|
||||||
|
}
|
||||||
|
return opts.Chain.Dial(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
func (tr *tcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
@ -90,14 +98,29 @@ func (tr *tcpTransporter) Multiplex() bool {
|
|||||||
|
|
||||||
// DialOptions describes the options for dialing.
|
// DialOptions describes the options for dialing.
|
||||||
type DialOptions struct {
|
type DialOptions struct {
|
||||||
|
Timeout time.Duration
|
||||||
|
Chain *Chain
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialOption allows a common way to set dial options.
|
// DialOption allows a common way to set dial options.
|
||||||
type DialOption func(opts *DialOptions)
|
type DialOption func(opts *DialOptions)
|
||||||
|
|
||||||
|
func TimeoutDialOption(timeout time.Duration) DialOption {
|
||||||
|
return func(opts *DialOptions) {
|
||||||
|
opts.Timeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChainDialOption(chain *Chain) DialOption {
|
||||||
|
return func(opts *DialOptions) {
|
||||||
|
opts.Chain = chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HandshakeOptions describes the options for handshake.
|
// HandshakeOptions describes the options for handshake.
|
||||||
type HandshakeOptions struct {
|
type HandshakeOptions struct {
|
||||||
Addr string
|
Addr string
|
||||||
|
Timeout time.Duration
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
WSOptions *WSOptions
|
WSOptions *WSOptions
|
||||||
KCPConfig *KCPConfig
|
KCPConfig *KCPConfig
|
||||||
@ -112,6 +135,12 @@ func AddrHandshakeOption(addr string) HandshakeOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TimeoutHandshakeOption(timeout time.Duration) HandshakeOption {
|
||||||
|
return func(opts *HandshakeOptions) {
|
||||||
|
opts.Timeout = timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
99
gost/cmd/gost/main.go
Normal file
99
gost/cmd/gost/main.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gost/gost"
|
||||||
|
"github.com/go-log/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
options struct {
|
||||||
|
chainNodes, serveNodes stringList
|
||||||
|
debugMode bool
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var (
|
||||||
|
configureFile string
|
||||||
|
printVersion bool
|
||||||
|
)
|
||||||
|
|
||||||
|
flag.Var(&options.chainNodes, "F", "forward address, can make a forward chain")
|
||||||
|
flag.Var(&options.serveNodes, "L", "listen address, can listen on multiple ports")
|
||||||
|
flag.StringVar(&configureFile, "C", "", "configure file")
|
||||||
|
flag.BoolVar(&options.debugMode, "D", false, "enable debug log")
|
||||||
|
flag.BoolVar(&printVersion, "V", false, "print version")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if err := loadConfigureFile(configureFile); err != nil {
|
||||||
|
log.Log(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag.NFlag() == 0 {
|
||||||
|
flag.PrintDefaults()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if printVersion {
|
||||||
|
fmt.Fprintf(os.Stderr, "gost %s (%s)\n", gost.Version, runtime.Version())
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildChain() (*gost.Chain, error) {
|
||||||
|
chain := gost.NewChain()
|
||||||
|
for _, cn := range options.chainNodes {
|
||||||
|
node, err := parseNode(cn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tr gost.Transporter
|
||||||
|
switch node.Transport {
|
||||||
|
case "tls":
|
||||||
|
tr = gost.TLSTransporter()
|
||||||
|
case "ws":
|
||||||
|
tr = gost.WSTransporter(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
var connector gost.Connector
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConfigureFile(configureFile string) error {
|
||||||
|
if configureFile == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
content, err := ioutil.ReadFile(configureFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(content, &options); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type stringList []string
|
||||||
|
|
||||||
|
func (l *stringList) String() string {
|
||||||
|
return fmt.Sprintf("%s", *l)
|
||||||
|
}
|
||||||
|
func (l *stringList) Set(value string) error {
|
||||||
|
*l = append(*l, value)
|
||||||
|
return nil
|
||||||
|
}
|
139
gost/cmd/gost/parser.go
Normal file
139
gost/cmd/gost/parser.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ginuerzh/gost/gost"
|
||||||
|
"github.com/go-log/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
Addr string
|
||||||
|
Protocol string // protocol: http/socks5/ss
|
||||||
|
Transport string // transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp
|
||||||
|
Remote string // remote address, used by tcp/udp port forwarding
|
||||||
|
Users []*url.Userinfo // authentication for proxy
|
||||||
|
Whitelist *gost.Permissions
|
||||||
|
Blacklist *gost.Permissions
|
||||||
|
values url.Values
|
||||||
|
serverName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseNode(s string) (n node, err error) {
|
||||||
|
if !strings.Contains(s, "://") {
|
||||||
|
s = "gost://" + s
|
||||||
|
}
|
||||||
|
u, err := url.Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
query := u.Query()
|
||||||
|
|
||||||
|
n = node{
|
||||||
|
Addr: u.Host,
|
||||||
|
}
|
||||||
|
|
||||||
|
if query.Get("whitelist") != "" {
|
||||||
|
if n.Whitelist, err = gost.ParsePermissions(query.Get("whitelist")); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// By default allow for everyting
|
||||||
|
n.Whitelist, _ = gost.ParsePermissions("*:*:*")
|
||||||
|
}
|
||||||
|
|
||||||
|
if query.Get("blacklist") != "" {
|
||||||
|
if n.Blacklist, err = gost.ParsePermissions(query.Get("blacklist")); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// By default block nothing
|
||||||
|
n.Blacklist, _ = gost.ParsePermissions("")
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.User != nil {
|
||||||
|
n.Users = append(n.Users, u.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
users, er := parseUsers(n.values.Get("secrets"))
|
||||||
|
if users != nil {
|
||||||
|
n.Users = append(n.Users, users...)
|
||||||
|
}
|
||||||
|
if er != nil {
|
||||||
|
log.Log("load secrets:", er)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(u.Host, ":") {
|
||||||
|
n.serverName, _, _ = net.SplitHostPort(u.Host)
|
||||||
|
if n.serverName == "" {
|
||||||
|
n.serverName = "localhost" // default server name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
schemes := strings.Split(u.Scheme, "+")
|
||||||
|
if len(schemes) == 1 {
|
||||||
|
n.Protocol = schemes[0]
|
||||||
|
n.Transport = schemes[0]
|
||||||
|
}
|
||||||
|
if len(schemes) == 2 {
|
||||||
|
n.Protocol = schemes[0]
|
||||||
|
n.Transport = schemes[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch n.Transport {
|
||||||
|
case "ws", "wss", "tls", "h2", "h2c", "quic", "kcp", "redirect", "ssu", "ssh":
|
||||||
|
case "https":
|
||||||
|
n.Protocol = "http"
|
||||||
|
n.Transport = "tls"
|
||||||
|
case "http2": // http2 -> http2+tls, h2c mode is http2+tcp
|
||||||
|
n.Protocol = "http2"
|
||||||
|
n.Transport = "tls"
|
||||||
|
case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
|
||||||
|
n.Remote = strings.Trim(u.EscapedPath(), "/")
|
||||||
|
case "rtcp", "rudp": // rtcp and rudp are for remote port forwarding
|
||||||
|
n.Remote = strings.Trim(u.EscapedPath(), "/")
|
||||||
|
default:
|
||||||
|
n.Transport = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
switch n.Protocol {
|
||||||
|
case "http", "http2", "socks", "socks4", "socks4a", "socks5", "ss":
|
||||||
|
default:
|
||||||
|
n.Protocol = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseUsers(s string) (users []*url.Userinfo, err error) {
|
||||||
|
if s == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Open(s)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimSpace(scanner.Text())
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s := strings.SplitN(line, " ", 2)
|
||||||
|
if len(s) == 1 {
|
||||||
|
users = append(users, url.User(strings.TrimSpace(s[0])))
|
||||||
|
} else if len(s) == 2 {
|
||||||
|
users = append(users, url.UserPassword(strings.TrimSpace(s[0]), strings.TrimSpace(s[1])))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = scanner.Err()
|
||||||
|
return
|
||||||
|
}
|
@ -37,5 +37,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.DefaultLogger = &logger{}
|
log.DefaultLogger = &LogLogger{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetLogger(logger log.Logger) {
|
||||||
|
log.DefaultLogger = logger
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,7 @@ 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{
|
options: &HandlerOptions{},
|
||||||
Chain: new(Chain),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(h.options)
|
opt(h.options)
|
||||||
|
68
gost/kcp.go
68
gost/kcp.go
@ -3,6 +3,7 @@ package gost
|
|||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@ -180,29 +181,61 @@ func KCPTransporter(config *KCPConfig) Transporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
|
func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
|
||||||
|
uaddr, err := net.ResolveUDPAddr("udp", addr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
tr.sessionMutex.Lock()
|
tr.sessionMutex.Lock()
|
||||||
defer tr.sessionMutex.Unlock()
|
defer tr.sessionMutex.Unlock()
|
||||||
|
|
||||||
session, ok := tr.sessions[addr]
|
session, ok := tr.sessions[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
session, err = tr.dial(addr, tr.config)
|
return net.DialUDP("udp", nil, uaddr)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
tr.sessions[addr] = session
|
return session.conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err = session.GetConn()
|
func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
|
opts := &HandshakeOptions{}
|
||||||
|
for _, option := range options {
|
||||||
|
option(opts)
|
||||||
|
}
|
||||||
|
config := tr.config
|
||||||
|
if opts.KCPConfig != nil {
|
||||||
|
config = opts.KCPConfig
|
||||||
|
}
|
||||||
|
tr.sessionMutex.Lock()
|
||||||
|
defer tr.sessionMutex.Unlock()
|
||||||
|
|
||||||
|
session, ok := tr.sessions[opts.Addr]
|
||||||
|
if !ok {
|
||||||
|
s, err := tr.initSession(opts.Addr, conn, config)
|
||||||
|
if err != nil {
|
||||||
|
conn.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
session = s
|
||||||
|
tr.sessions[opts.Addr] = session
|
||||||
|
}
|
||||||
|
cc, err := session.GetConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.Close()
|
session.Close()
|
||||||
delete(tr.sessions, addr) // TODO: we could obtain a new session automatically.
|
delete(tr.sessions, opts.Addr)
|
||||||
}
|
return nil, err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *kcpTransporter) dial(addr string, config *KCPConfig) (*kcpSession, error) {
|
return cc, nil
|
||||||
kcpconn, err := kcp.DialWithOptions(addr,
|
}
|
||||||
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard)
|
|
||||||
|
func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*kcpSession, error) {
|
||||||
|
pc, ok := conn.(net.PacketConn)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("wrong connection type")
|
||||||
|
}
|
||||||
|
|
||||||
|
kcpconn, err := kcp.NewConn(addr,
|
||||||
|
blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard, pc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -227,22 +260,17 @@ func (tr *kcpTransporter) dial(addr string, config *KCPConfig) (*kcpSession, err
|
|||||||
// stream multiplex
|
// stream multiplex
|
||||||
smuxConfig := smux.DefaultConfig()
|
smuxConfig := smux.DefaultConfig()
|
||||||
smuxConfig.MaxReceiveBuffer = config.SockBuf
|
smuxConfig.MaxReceiveBuffer = config.SockBuf
|
||||||
var conn net.Conn = kcpconn
|
var cc net.Conn = kcpconn
|
||||||
if !config.NoComp {
|
if !config.NoComp {
|
||||||
conn = newCompStreamConn(kcpconn)
|
cc = newCompStreamConn(kcpconn)
|
||||||
}
|
}
|
||||||
session, err := smux.Client(conn, smuxConfig)
|
session, err := smux.Client(cc, smuxConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Close()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &kcpSession{conn: conn, session: session}, nil
|
return &kcpSession{conn: conn, session: session}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *kcpTransporter) Multiplex() bool {
|
func (tr *kcpTransporter) Multiplex() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -284,7 +312,7 @@ func KCPListener(addr string, config *KCPConfig) (Listener, error) {
|
|||||||
l := &kcpListener{
|
l := &kcpListener{
|
||||||
config: config,
|
config: config,
|
||||||
ln: ln,
|
ln: ln,
|
||||||
connChan: make(chan net.Conn, 128),
|
connChan: make(chan net.Conn, 1024),
|
||||||
errChan: make(chan error),
|
errChan: make(chan error),
|
||||||
}
|
}
|
||||||
go l.acceptLoop()
|
go l.acceptLoop()
|
||||||
|
19
gost/log.go
19
gost/log.go
@ -1,18 +1,29 @@
|
|||||||
package gost
|
package gost
|
||||||
|
|
||||||
import "log"
|
import (
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
type logger struct {
|
type LogLogger struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *logger) Log(v ...interface{}) {
|
func (l *LogLogger) Log(v ...interface{}) {
|
||||||
log.Println(v...)
|
log.Println(v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *logger) Logf(format string, v ...interface{}) {
|
func (l *LogLogger) Logf(format string, v ...interface{}) {
|
||||||
log.Printf(format, v...)
|
log.Printf(format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NopLogger struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *NopLogger) Log(v ...interface{}) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *NopLogger) Logf(format string, v ...interface{}) {
|
||||||
|
}
|
||||||
|
185
gost/permissions.go
Normal file
185
gost/permissions.go
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
glob "github.com/ryanuber/go-glob"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PortRange struct {
|
||||||
|
Min, Max int
|
||||||
|
}
|
||||||
|
|
||||||
|
type PortSet []PortRange
|
||||||
|
|
||||||
|
type StringSet []string
|
||||||
|
|
||||||
|
type Permission struct {
|
||||||
|
Actions StringSet
|
||||||
|
Hosts StringSet
|
||||||
|
Ports PortSet
|
||||||
|
}
|
||||||
|
|
||||||
|
type Permissions []Permission
|
||||||
|
|
||||||
|
func minint(x, y int) int {
|
||||||
|
if x < y {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxint(x, y int) int {
|
||||||
|
if x > y {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ir *PortRange) Contains(value int) bool {
|
||||||
|
return value >= ir.Min && value <= ir.Max
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePortRange(s string) (*PortRange, error) {
|
||||||
|
if s == "*" {
|
||||||
|
return &PortRange{Min: 0, Max: 65535}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
minmax := strings.Split(s, "-")
|
||||||
|
switch len(minmax) {
|
||||||
|
case 1:
|
||||||
|
port, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if port < 0 || port > 65535 {
|
||||||
|
return nil, fmt.Errorf("invalid port: %s", s)
|
||||||
|
}
|
||||||
|
return &PortRange{Min: port, Max: port}, nil
|
||||||
|
case 2:
|
||||||
|
min, err := strconv.Atoi(minmax[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
max, err := strconv.Atoi(minmax[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
realmin := maxint(0, minint(min, max))
|
||||||
|
realmax := minint(65535, maxint(min, max))
|
||||||
|
|
||||||
|
return &PortRange{Min: realmin, Max: realmax}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid range: %s", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *PortSet) Contains(value int) bool {
|
||||||
|
for _, portRange := range *ps {
|
||||||
|
if portRange.Contains(value) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePortSet(s string) (*PortSet, error) {
|
||||||
|
ps := &PortSet{}
|
||||||
|
|
||||||
|
if s == "" {
|
||||||
|
return nil, errors.New("must specify at least one port")
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges := strings.Split(s, ",")
|
||||||
|
|
||||||
|
for _, r := range ranges {
|
||||||
|
portRange, err := ParsePortRange(r)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
*ps = append(*ps, *portRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *StringSet) Contains(subj string) bool {
|
||||||
|
for _, s := range *ss {
|
||||||
|
if glob.Glob(s, subj) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseStringSet(s string) (*StringSet, error) {
|
||||||
|
ss := &StringSet{}
|
||||||
|
if s == "" {
|
||||||
|
return nil, errors.New("cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
*ss = strings.Split(s, ",")
|
||||||
|
|
||||||
|
return ss, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *Permissions) Can(action string, host string, port int) bool {
|
||||||
|
for _, p := range *ps {
|
||||||
|
if p.Actions.Contains(action) && p.Hosts.Contains(host) && p.Ports.Contains(port) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePermissions(s string) (*Permissions, error) {
|
||||||
|
ps := &Permissions{}
|
||||||
|
|
||||||
|
if s == "" {
|
||||||
|
return &Permissions{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
perms := strings.Split(s, " ")
|
||||||
|
|
||||||
|
for _, perm := range perms {
|
||||||
|
parts := strings.Split(perm, ":")
|
||||||
|
|
||||||
|
switch len(parts) {
|
||||||
|
case 3:
|
||||||
|
actions, err := ParseStringSet(parts[0])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("action list must look like connect,bind given: %s", parts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts, err := ParseStringSet(parts[1])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("hosts list must look like google.pl,*.google.com given: %s", parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
ports, err := ParsePortSet(parts[2])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("ports list must look like 80,8000-9000, given: %s", parts[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
permission := Permission{Actions: *actions, Hosts: *hosts, Ports: *ports}
|
||||||
|
|
||||||
|
*ps = append(*ps, permission)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("permission must have format [actions]:[hosts]:[ports] given: %s", perm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps, nil
|
||||||
|
}
|
152
gost/permissions_test.go
Normal file
152
gost/permissions_test.go
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
package gost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var portRangeTests = []struct {
|
||||||
|
in string
|
||||||
|
out *PortRange
|
||||||
|
}{
|
||||||
|
{"1", &PortRange{Min: 1, Max: 1}},
|
||||||
|
{"1-3", &PortRange{Min: 1, Max: 3}},
|
||||||
|
{"3-1", &PortRange{Min: 1, Max: 3}},
|
||||||
|
{"0-100000", &PortRange{Min: 0, Max: 65535}},
|
||||||
|
{"*", &PortRange{Min: 0, Max: 65535}},
|
||||||
|
}
|
||||||
|
|
||||||
|
var stringSetTests = []struct {
|
||||||
|
in string
|
||||||
|
out *StringSet
|
||||||
|
}{
|
||||||
|
{"*", &StringSet{"*"}},
|
||||||
|
{"google.pl,google.com", &StringSet{"google.pl", "google.com"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
var portSetTests = []struct {
|
||||||
|
in string
|
||||||
|
out *PortSet
|
||||||
|
}{
|
||||||
|
{"1,3", &PortSet{PortRange{Min: 1, Max: 1}, PortRange{Min: 3, Max: 3}}},
|
||||||
|
{"1-3,7-5", &PortSet{PortRange{Min: 1, Max: 3}, PortRange{Min: 5, Max: 7}}},
|
||||||
|
{"0-100000", &PortSet{PortRange{Min: 0, Max: 65535}}},
|
||||||
|
{"*", &PortSet{PortRange{Min: 0, Max: 65535}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
var permissionsTests = []struct {
|
||||||
|
in string
|
||||||
|
out *Permissions
|
||||||
|
}{
|
||||||
|
{"", &Permissions{}},
|
||||||
|
{"*:*:*", &Permissions{
|
||||||
|
Permission{
|
||||||
|
Actions: StringSet{"*"},
|
||||||
|
Hosts: StringSet{"*"},
|
||||||
|
Ports: PortSet{PortRange{Min: 0, Max: 65535}},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{"bind:127.0.0.1,localhost:80,443,8000-8100 connect:*.google.pl:80,443", &Permissions{
|
||||||
|
Permission{
|
||||||
|
Actions: StringSet{"bind"},
|
||||||
|
Hosts: StringSet{"127.0.0.1", "localhost"},
|
||||||
|
Ports: PortSet{
|
||||||
|
PortRange{Min: 80, Max: 80},
|
||||||
|
PortRange{Min: 443, Max: 443},
|
||||||
|
PortRange{Min: 8000, Max: 8100},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Permission{
|
||||||
|
Actions: StringSet{"connect"},
|
||||||
|
Hosts: StringSet{"*.google.pl"},
|
||||||
|
Ports: PortSet{
|
||||||
|
PortRange{Min: 80, Max: 80},
|
||||||
|
PortRange{Min: 443, Max: 443},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortRangeParse(t *testing.T) {
|
||||||
|
for _, test := range portRangeTests {
|
||||||
|
actual, err := ParsePortRange(test.in)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePortRange(%q) returned error: %v", test.in, err)
|
||||||
|
} else if *actual != *test.out {
|
||||||
|
t.Errorf("ParsePortRange(%q): got %v, want %v", test.in, actual, test.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortRangeContains(t *testing.T) {
|
||||||
|
actual, _ := ParsePortRange("5-10")
|
||||||
|
|
||||||
|
if !actual.Contains(5) || !actual.Contains(7) || !actual.Contains(10) {
|
||||||
|
t.Errorf("5-10 should contain 5, 7 and 10")
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual.Contains(4) || actual.Contains(11) {
|
||||||
|
t.Errorf("5-10 should not contain 4, 11")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringSetParse(t *testing.T) {
|
||||||
|
for _, test := range stringSetTests {
|
||||||
|
actual, err := ParseStringSet(test.in)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParseStringSet(%q) returned error: %v", test.in, err)
|
||||||
|
} else if fmt.Sprintln(actual) != fmt.Sprintln(test.out) {
|
||||||
|
t.Errorf("ParseStringSet(%q): got %v, want %v", test.in, actual, test.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringSetContains(t *testing.T) {
|
||||||
|
ss, _ := ParseStringSet("google.pl,*.google.com")
|
||||||
|
|
||||||
|
if !ss.Contains("google.pl") || !ss.Contains("www.google.com") {
|
||||||
|
t.Errorf("google.pl,*.google.com should contain google.pl and www.google.com")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ss.Contains("www.google.pl") || ss.Contains("foobar.com") {
|
||||||
|
t.Errorf("google.pl,*.google.com shound not contain www.google.pl and foobar.com")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortSetParse(t *testing.T) {
|
||||||
|
for _, test := range portSetTests {
|
||||||
|
actual, err := ParsePortSet(test.in)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePortRange(%q) returned error: %v", test.in, err)
|
||||||
|
} else if fmt.Sprintln(actual) != fmt.Sprintln(test.out) {
|
||||||
|
t.Errorf("ParsePortRange(%q): got %v, want %v", test.in, actual, test.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortSetContains(t *testing.T) {
|
||||||
|
actual, _ := ParsePortSet("5-10,20-30")
|
||||||
|
|
||||||
|
if !actual.Contains(5) || !actual.Contains(7) || !actual.Contains(10) {
|
||||||
|
t.Errorf("5-10,20-30 should contain 5, 7 and 10")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !actual.Contains(20) || !actual.Contains(27) || !actual.Contains(30) {
|
||||||
|
t.Errorf("5-10,20-30 should contain 20, 27 and 30")
|
||||||
|
}
|
||||||
|
|
||||||
|
if actual.Contains(4) || actual.Contains(11) || actual.Contains(31) {
|
||||||
|
t.Errorf("5-10,20-30 should not contain 4, 11, 31")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPermissionsParse(t *testing.T) {
|
||||||
|
for _, test := range permissionsTests {
|
||||||
|
actual, err := ParsePermissions(test.in)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePermissions(%q) returned error: %v", test.in, err)
|
||||||
|
} else if fmt.Sprintln(actual) != fmt.Sprintln(test.out) {
|
||||||
|
t.Errorf("ParsePermissions(%q): got %v, want %v", test.in, actual, test.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,31 +2,42 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/ginuerzh/gost/gost"
|
"github.com/ginuerzh/gost/gost"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
quiet bool
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
gost.Debug = true
|
|
||||||
|
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() {
|
func main() {
|
||||||
// go httpServer()
|
go httpServer()
|
||||||
// go socks5Server()
|
go socks5Server()
|
||||||
// go tlsServer()
|
go tlsServer()
|
||||||
// go shadowServer()
|
go shadowServer()
|
||||||
// go wsServer()
|
go wsServer()
|
||||||
// go wssServer()
|
go wssServer()
|
||||||
// go kcpServer()
|
go kcpServer()
|
||||||
// go tcpForwardServer()
|
// go tcpForwardServer()
|
||||||
// go rtcpForwardServer()
|
// go rtcpForwardServer()
|
||||||
// go rudpForwardServer()
|
// go rudpForwardServer()
|
||||||
// go tcpRedirectServer()
|
// go tcpRedirectServer()
|
||||||
go http2Server()
|
// go http2Server()
|
||||||
|
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
@ -36,7 +47,7 @@ func httpServer() {
|
|||||||
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")
|
ln, err := gost.TCPListener(":18080")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -49,7 +60,7 @@ func socks5Server() {
|
|||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
gost.TLSConfigHandlerOption(tlsConfig()),
|
gost.TLSConfigHandlerOption(tlsConfig()),
|
||||||
))
|
))
|
||||||
ln, err := gost.TCPListener(":1080")
|
ln, err := gost.TCPListener(":11080")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -61,7 +72,7 @@ func shadowServer() {
|
|||||||
s.Handle(gost.ShadowHandler(
|
s.Handle(gost.ShadowHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
|
||||||
))
|
))
|
||||||
ln, err := gost.TCPListener(":8338")
|
ln, err := gost.TCPListener(":18338")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -73,7 +84,7 @@ func tlsServer() {
|
|||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
))
|
))
|
||||||
ln, err := gost.TLSListener(":1443", tlsConfig())
|
ln, err := gost.TLSListener(":11443", tlsConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -85,7 +96,7 @@ func wsServer() {
|
|||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
))
|
))
|
||||||
ln, err := gost.WSListener(":8000", nil)
|
ln, err := gost.WSListener(":18000", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -97,7 +108,7 @@ func wssServer() {
|
|||||||
s.Handle(gost.HTTPHandler(
|
s.Handle(gost.HTTPHandler(
|
||||||
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
|
||||||
))
|
))
|
||||||
ln, err := gost.WSSListener(":8443", &gost.WSOptions{TLSConfig: tlsConfig()})
|
ln, err := gost.WSSListener(":18443", &gost.WSOptions{TLSConfig: tlsConfig()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -107,7 +118,7 @@ func wssServer() {
|
|||||||
func kcpServer() {
|
func kcpServer() {
|
||||||
s := &gost.Server{}
|
s := &gost.Server{}
|
||||||
s.Handle(gost.HTTPHandler())
|
s.Handle(gost.HTTPHandler())
|
||||||
ln, err := gost.KCPListener(":8388", nil)
|
ln, err := gost.KCPListener(":18388", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tlsTransporter struct {
|
type tlsTransporter struct {
|
||||||
|
*tcpTransporter
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSTransporter creates a Transporter that is used by TLS proxy client.
|
// TLSTransporter creates a Transporter that is used by TLS proxy client.
|
||||||
@ -14,10 +15,6 @@ func TLSTransporter() Transporter {
|
|||||||
return &tlsTransporter{}
|
return &tlsTransporter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *tlsTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
|
||||||
return net.Dial("tcp", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
opts := &HandshakeOptions{}
|
opts := &HandshakeOptions{}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
|
14
gost/ws.go
14
gost/ws.go
@ -98,6 +98,7 @@ func (c *websocketConn) SetWriteDeadline(t time.Time) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wsTransporter struct {
|
type wsTransporter struct {
|
||||||
|
*tcpTransporter
|
||||||
options *WSOptions
|
options *WSOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,10 +109,6 @@ func WSTransporter(opts *WSOptions) Transporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wsTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
|
||||||
return net.Dial("tcp", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
opts := &HandshakeOptions{}
|
opts := &HandshakeOptions{}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
@ -130,6 +127,7 @@ func (tr *wsTransporter) Multiplex() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type wssTransporter struct {
|
type wssTransporter struct {
|
||||||
|
*tcpTransporter
|
||||||
options *WSOptions
|
options *WSOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +138,6 @@ func WSSTransporter(opts *WSOptions) Transporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tr *wssTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
|
|
||||||
return net.Dial("tcp", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
|
||||||
opts := &HandshakeOptions{}
|
opts := &HandshakeOptions{}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
@ -189,7 +183,7 @@ func WSListener(addr string, options *WSOptions) (Listener, error) {
|
|||||||
CheckOrigin: func(r *http.Request) bool { return true },
|
CheckOrigin: func(r *http.Request) bool { return true },
|
||||||
EnableCompression: options.EnableCompression,
|
EnableCompression: options.EnableCompression,
|
||||||
},
|
},
|
||||||
connChan: make(chan net.Conn, 128),
|
connChan: make(chan net.Conn, 1024),
|
||||||
errChan: make(chan error, 1),
|
errChan: make(chan error, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +268,7 @@ func WSSListener(addr string, options *WSOptions) (Listener, error) {
|
|||||||
CheckOrigin: func(r *http.Request) bool { return true },
|
CheckOrigin: func(r *http.Request) bool { return true },
|
||||||
EnableCompression: options.EnableCompression,
|
EnableCompression: options.EnableCompression,
|
||||||
},
|
},
|
||||||
connChan: make(chan net.Conn, 128),
|
connChan: make(chan net.Conn, 1024),
|
||||||
errChan: make(chan error, 1),
|
errChan: make(chan error, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user