strategy: add checktimeout config. (#89)

This commit is contained in:
nadoo 2019-03-18 23:37:01 +08:00
parent 47406ce4ce
commit a22b1d9c86
12 changed files with 91 additions and 74 deletions

View File

@ -116,9 +116,11 @@ glider -config CONFIGPATH -listen :8080 -verbose
## Usage ## Usage
```bash ```bash
glider v0.6.10 usage: glider v0.7.0 usage:
-checkinterval int -checkinterval int
proxy check interval(seconds) (default 30) proxy check interval(seconds) (default 30)
-checktimeout int
proxy check timeout(seconds) (default 10)
-checkwebsite string -checkwebsite string
proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80 (default "www.apple.com") proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80 (default "www.apple.com")
-config string -config string
@ -139,6 +141,8 @@ glider v0.6.10 usage:
timeout value used in multiple dnsservers switch(seconds) (default 3) timeout value used in multiple dnsservers switch(seconds) (default 3)
-forward value -forward value
forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS] forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]
-include value
include file
-interface string -interface string
source ip or source interface source ip or source interface
-listen value -listen value

View File

@ -7,41 +7,35 @@ import (
"time" "time"
) )
// UDPBufSize is the size of udp buffer // UDPBufSize is the size of udp buffer.
const UDPBufSize = 65536 const UDPBufSize = 65536
// Conn struct // Conn is a base conn struct.
type Conn struct { type Conn struct {
r *bufio.Reader r *bufio.Reader
net.Conn net.Conn
} }
// NewConn . // NewConn returns a new conn.
func NewConn(c net.Conn) *Conn { func NewConn(c net.Conn) *Conn {
return &Conn{bufio.NewReader(c), c} return &Conn{bufio.NewReader(c), c}
} }
// NewConnSize . // Peek returns the next n bytes without advancing the reader.
func NewConnSize(c net.Conn, n int) *Conn {
return &Conn{bufio.NewReaderSize(c, n), c}
}
// Peek .
func (c *Conn) Peek(n int) ([]byte, error) { func (c *Conn) Peek(n int) ([]byte, error) {
return c.r.Peek(n) return c.r.Peek(n)
} }
// Read .
func (c *Conn) Read(p []byte) (int, error) { func (c *Conn) Read(p []byte) (int, error) {
return c.r.Read(p) return c.r.Read(p)
} }
// Reader returns the internal bufio.Reader // Reader returns the internal bufio.Reader.
func (c *Conn) Reader() *bufio.Reader { func (c *Conn) Reader() *bufio.Reader {
return c.r return c.r
} }
// Relay . // Relay relays between left and right.
func Relay(left, right net.Conn) (int64, int64, error) { func Relay(left, right net.Conn) (int64, int64, error) {
type res struct { type res struct {
N int64 N int64
@ -67,8 +61,8 @@ func Relay(left, right net.Conn) (int64, int64, error) {
return n, rs.N, err return n, rs.N, err
} }
// TimedCopy copy from src to dst at target with read timeout // RelayUDP copys from src to dst at target with read timeout.
func TimedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration) error { func RelayUDP(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration) error {
buf := make([]byte, UDPBufSize) buf := make([]byte, UDPBufSize)
for { for {
src.SetReadDeadline(time.Now().Add(timeout)) src.SetReadDeadline(time.Now().Add(timeout))
@ -84,7 +78,7 @@ func TimedCopy(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout
} }
} }
// OutboundIP returns preferred outbound ip of this machine // OutboundIP returns preferred outbound ip of this machine.
func OutboundIP() string { func OutboundIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80") conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil { if err != nil {

View File

@ -40,6 +40,7 @@ func confInit() {
flag.StringVar(&conf.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr") flag.StringVar(&conf.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr")
flag.StringVar(&conf.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") flag.StringVar(&conf.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)") flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)")
flag.IntVar(&conf.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(seconds)")
flag.IntVar(&conf.StrategyConfig.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled") flag.IntVar(&conf.StrategyConfig.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled")
flag.StringVar(&conf.StrategyConfig.IntFace, "interface", "", "source ip or source interface") flag.StringVar(&conf.StrategyConfig.IntFace, "interface", "", "source ip or source interface")

View File

@ -155,6 +155,8 @@ checkwebsite=www.apple.com
# check interval(seconds) # check interval(seconds)
checkinterval=30 checkinterval=30
# check timeout(seconds)
checktimeout=10
# DNS FORWARDING SERVER # DNS FORWARDING SERVER
# ---------------- # ----------------

6
go.mod
View File

@ -19,9 +19,9 @@ require (
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
github.com/tjfoc/gmsm v1.0.1 // indirect github.com/tjfoc/gmsm v1.0.1 // indirect
github.com/xtaci/kcp-go v5.0.7+incompatible github.com/xtaci/kcp-go v5.0.7+incompatible
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a
golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect golang.org/x/net v0.0.0-20190313220215-9f648a60d977 // indirect
golang.org/x/sys v0.0.0-20190312061237-fead79001313 // indirect golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f // indirect
) )
// Replace dependency modules with local developing copy // Replace dependency modules with local developing copy

6
go.sum
View File

@ -38,6 +38,8 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95 h1:fY7Dsw114eJN4boqzVSbpVHO6rTdhq6/GnXeu+PKnzU= golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95 h1:fY7Dsw114eJN4boqzVSbpVHO6rTdhq6/GnXeu+PKnzU=
golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190310074541-c10a0554eabf h1:J7RqX9u0J9ZB37CGaFc2VC+QZZT6E6jnDbrboEFVo0U= golang.org/x/net v0.0.0-20190310074541-c10a0554eabf h1:J7RqX9u0J9ZB37CGaFc2VC+QZZT6E6jnDbrboEFVo0U=
@ -46,6 +48,8 @@ golang.org/x/net v0.0.0-20190311031020-56fb01167e7d h1:vQJbQvu6+H699vOmHa20TEBI9
golang.org/x/net v0.0.0-20190311031020-56fb01167e7d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311031020-56fb01167e7d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190302025703-b6889370fb10 h1:xQJI9OEiErEQ++DoXOHqEpzsGMrAv2Q2jyCpi7DmfpQ= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10 h1:xQJI9OEiErEQ++DoXOHqEpzsGMrAv2Q2jyCpi7DmfpQ=
golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -69,4 +73,6 @@ golang.org/x/sys v0.0.0-20190311152110-c8c8c57fd1e1 h1:FQNj2xvjQ1lgFyzbSybGZr792
golang.org/x/sys v0.0.0-20190311152110-c8c8c57fd1e1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190311152110-c8c8c57fd1e1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f h1:yCrMx/EeIue0+Qca57bWZS7VX6ymEoypmhWyPhz0NHM=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -26,10 +26,10 @@ import (
"github.com/nadoo/glider/proxy" "github.com/nadoo/glider/proxy"
) )
// Version is socks5 version number // Version is socks5 version number.
const Version = 5 const Version = 5
// SOCKS5 struct // SOCKS5 is a base socks5 struct.
type SOCKS5 struct { type SOCKS5 struct {
dialer proxy.Dialer dialer proxy.Dialer
addr string addr string
@ -43,7 +43,7 @@ func init() {
} }
// NewSOCKS5 returns a Proxy that makes SOCKS v5 connections to the given address // NewSOCKS5 returns a Proxy that makes SOCKS v5 connections to the given address
// with an optional username and password. See RFC 1928 // with an optional username and password. (RFC 1928)
func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) { func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
@ -65,23 +65,23 @@ func NewSOCKS5(s string, dialer proxy.Dialer) (*SOCKS5, error) {
return h, nil return h, nil
} }
// NewSocks5Dialer returns a socks5 proxy dialer // NewSocks5Dialer returns a socks5 proxy dialer.
func NewSocks5Dialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewSocks5Dialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewSOCKS5(s, dialer) return NewSOCKS5(s, dialer)
} }
// NewSocks5Server returns a socks5 proxy server // NewSocks5Server returns a socks5 proxy server.
func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewSocks5Server(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewSOCKS5(s, dialer) return NewSOCKS5(s, dialer)
} }
// ListenAndServe serves socks5 requests // ListenAndServe serves socks5 requests.
func (s *SOCKS5) ListenAndServe() { func (s *SOCKS5) ListenAndServe() {
go s.ListenAndServeUDP() go s.ListenAndServeUDP()
s.ListenAndServeTCP() s.ListenAndServeTCP()
} }
// ListenAndServeTCP . // ListenAndServeTCP listen and serve on tcp port.
func (s *SOCKS5) ListenAndServeTCP() { func (s *SOCKS5) ListenAndServeTCP() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
@ -102,7 +102,7 @@ func (s *SOCKS5) ListenAndServeTCP() {
} }
} }
// Serve . // Serve serves a connection.
func (s *SOCKS5) Serve(c net.Conn) { func (s *SOCKS5) Serve(c net.Conn) {
defer c.Close() defer c.Close()
@ -148,7 +148,7 @@ func (s *SOCKS5) Serve(c net.Conn) {
} }
} }
// ListenAndServeUDP serves udp requests // ListenAndServeUDP serves udp requests.
func (s *SOCKS5) ListenAndServeUDP() { func (s *SOCKS5) ListenAndServeUDP() {
lc, err := net.ListenPacket("udp", s.addr) lc, err := net.ListenPacket("udp", s.addr)
if err != nil { if err != nil {
@ -189,7 +189,7 @@ func (s *SOCKS5) ListenAndServeUDP() {
nm.Store(raddr.String(), pc) nm.Store(raddr.String(), pc)
go func() { go func() {
conn.TimedCopy(c, raddr, pc, 2*time.Minute) conn.RelayUDP(c, raddr, pc, 2*time.Minute)
pc.Close() pc.Close()
nm.Delete(raddr.String()) nm.Delete(raddr.String())
}() }()
@ -211,7 +211,7 @@ func (s *SOCKS5) ListenAndServeUDP() {
} }
// Addr returns forwarder's address // Addr returns forwarder's address.
func (s *SOCKS5) Addr() string { func (s *SOCKS5) Addr() string {
if s.addr == "" { if s.addr == "" {
return s.dialer.Addr() return s.dialer.Addr()
@ -219,7 +219,7 @@ func (s *SOCKS5) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer // NextDialer returns the next dialer.
func (s *SOCKS5) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } func (s *SOCKS5) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
// Dial connects to the address addr on the network net via the SOCKS5 proxy. // Dial connects to the address addr on the network net via the SOCKS5 proxy.
@ -244,7 +244,7 @@ func (s *SOCKS5) Dial(network, addr string) (net.Conn, error) {
return c, nil return c, nil
} }
// DialUDP connects to the given address via the proxy // DialUDP connects to the given address via the proxy.
func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
c, err := s.dialer.Dial("tcp", s.addr) c, err := s.dialer.Dial("tcp", s.addr)
if err != nil { if err != nil {
@ -293,7 +293,7 @@ func (s *SOCKS5) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.A
// connect takes an existing connection to a socks5 proxy server, // connect takes an existing connection to a socks5 proxy server,
// and commands the server to extend that connection to target, // and commands the server to extend that connection to target,
// which must be a canonical address with a host and port // which must be a canonical address with a host and port.
func (s *SOCKS5) connect(conn net.Conn, target string) error { func (s *SOCKS5) connect(conn net.Conn, target string) error {
host, portStr, err := net.SplitHostPort(target) host, portStr, err := net.SplitHostPort(target)
if err != nil { if err != nil {
@ -424,7 +424,7 @@ func (s *SOCKS5) connect(conn net.Conn, target string) error {
return nil return nil
} }
// Handshake fast-tracks SOCKS initialization to get target address to connect // Handshake fast-tracks SOCKS initialization to get target address to connect.
func (s *SOCKS5) handshake(rw io.ReadWriter) (socks.Addr, error) { func (s *SOCKS5) handshake(rw io.ReadWriter) (socks.Addr, error) {
// Read RFC 1928 for request and reply structure and sizes // Read RFC 1928 for request and reply structure and sizes
buf := make([]byte, socks.MaxAddrLen) buf := make([]byte, socks.MaxAddrLen)

View File

@ -16,7 +16,7 @@ import (
"github.com/nadoo/glider/proxy" "github.com/nadoo/glider/proxy"
) )
// SS . // SS is a base ss struct.
type SS struct { type SS struct {
dialer proxy.Dialer dialer proxy.Dialer
addr string addr string
@ -29,7 +29,7 @@ func init() {
proxy.RegisterServer("ss", NewSSServer) proxy.RegisterServer("ss", NewSSServer)
} }
// NewSS returns a shadowsocks proxy // NewSS returns a ss proxy.
func NewSS(s string, dialer proxy.Dialer) (*SS, error) { func NewSS(s string, dialer proxy.Dialer) (*SS, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
@ -55,23 +55,23 @@ func NewSS(s string, dialer proxy.Dialer) (*SS, error) {
return p, nil return p, nil
} }
// NewSSDialer returns a ss proxy dialer // NewSSDialer returns a ss proxy dialer.
func NewSSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) { func NewSSDialer(s string, dialer proxy.Dialer) (proxy.Dialer, error) {
return NewSS(s, dialer) return NewSS(s, dialer)
} }
// NewSSServer returns a ss proxy server // NewSSServer returns a ss proxy server.
func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewSSServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewSS(s, dialer) return NewSS(s, dialer)
} }
// ListenAndServe serves ss requests // ListenAndServe serves ss requests.
func (s *SS) ListenAndServe() { func (s *SS) ListenAndServe() {
go s.ListenAndServeUDP() go s.ListenAndServeUDP()
s.ListenAndServeTCP() s.ListenAndServeTCP()
} }
// ListenAndServeTCP serves tcp ss requests // ListenAndServeTCP serves tcp ss requests.
func (s *SS) ListenAndServeTCP() { func (s *SS) ListenAndServeTCP() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
@ -92,7 +92,7 @@ func (s *SS) ListenAndServeTCP() {
} }
// Serve serves tcp ss requests // Serve serves a connection.
func (s *SS) Serve(c net.Conn) { func (s *SS) Serve(c net.Conn) {
defer c.Close() defer c.Close()
@ -166,7 +166,7 @@ func (s *SS) Serve(c net.Conn) {
} }
// ListenAndServeUDP serves udp ss requests // ListenAndServeUDP serves udp ss requests.
func (s *SS) ListenAndServeUDP() { func (s *SS) ListenAndServeUDP() {
lc, err := net.ListenPacket("udp", s.addr) lc, err := net.ListenPacket("udp", s.addr)
if err != nil { if err != nil {
@ -204,7 +204,7 @@ func (s *SS) ListenAndServeUDP() {
nm.Store(raddr.String(), pc) nm.Store(raddr.String(), pc)
go func() { go func() {
conn.TimedCopy(c, raddr, pc, 2*time.Minute) conn.RelayUDP(c, raddr, pc, 2*time.Minute)
pc.Close() pc.Close()
nm.Delete(raddr.String()) nm.Delete(raddr.String())
}() }()
@ -225,12 +225,12 @@ func (s *SS) ListenAndServeUDP() {
} }
} }
// ListCipher . // ListCipher returns all the ciphers supported.
func ListCipher() string { func ListCipher() string {
return strings.Join(core.ListCipher(), " ") return strings.Join(core.ListCipher(), " ")
} }
// Addr returns forwarder's address // Addr returns forwarder's address.
func (s *SS) Addr() string { func (s *SS) Addr() string {
if s.addr == "" { if s.addr == "" {
return s.dialer.Addr() return s.dialer.Addr()
@ -238,7 +238,7 @@ func (s *SS) Addr() string {
return s.addr return s.addr
} }
// NextDialer returns the next dialer // NextDialer returns the next dialer.
func (s *SS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) } func (s *SS) NextDialer(dstAddr string) proxy.Dialer { return s.dialer.NextDialer(dstAddr) }
// Dial connects to the address addr on the network net via the proxy. // Dial connects to the address addr on the network net via the proxy.
@ -268,7 +268,7 @@ func (s *SS) Dial(network, addr string) (net.Conn, error) {
} }
// DialUDP connects to the given address via the proxy // DialUDP connects to the given address via the proxy.
func (s *SS) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) { func (s *SS) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
pc, nextHop, err := s.dialer.DialUDP(network, s.addr) pc, nextHop, err := s.dialer.DialUDP(network, s.addr)
if err != nil { if err != nil {

View File

@ -16,8 +16,8 @@ import (
type UDPTun struct { type UDPTun struct {
dialer proxy.Dialer dialer proxy.Dialer
addr string addr string
taddr string // tunnel addr taddr string // tunnel addr string
uaddr *net.UDPAddr // tunnel addr tuaddr *net.UDPAddr // tunnel addr
} }
func init() { func init() {
@ -41,7 +41,7 @@ func NewUDPTun(s string, dialer proxy.Dialer) (*UDPTun, error) {
taddr: d[1], taddr: d[1],
} }
p.uaddr, err = net.ResolveUDPAddr("udp", p.taddr) p.tuaddr, err = net.ResolveUDPAddr("udp", p.taddr)
return p, err return p, err
} }
@ -85,7 +85,7 @@ func (s *UDPTun) ListenAndServe() {
nm.Store(raddr.String(), pc) nm.Store(raddr.String(), pc)
go func() { go func() {
conn.TimedCopy(c, raddr, pc, 2*time.Minute) conn.RelayUDP(c, raddr, pc, 2*time.Minute)
pc.Close() pc.Close()
nm.Delete(raddr.String()) nm.Delete(raddr.String())
}() }()
@ -94,7 +94,7 @@ func (s *UDPTun) ListenAndServe() {
pc = v.(net.PacketConn) pc = v.(net.PacketConn)
} }
_, err = pc.WriteTo(buf[:n], s.uaddr) _, err = pc.WriteTo(buf[:n], s.tuaddr)
if err != nil { if err != nil {
log.F("[udptun] remote write error: %v", err) log.F("[udptun] remote write error: %v", err)
continue continue

View File

@ -12,7 +12,7 @@ import (
"github.com/nadoo/glider/proxy" "github.com/nadoo/glider/proxy"
) )
// UoTTun udp over tcp tunnel // UoTTun is a base udp over tcp tunnel struct.
type UoTTun struct { type UoTTun struct {
dialer proxy.Dialer dialer proxy.Dialer
addr string addr string
@ -24,7 +24,7 @@ func init() {
proxy.RegisterServer("uottun", NewUoTTunServer) proxy.RegisterServer("uottun", NewUoTTunServer)
} }
// NewUoTTun returns a UoTTun proxy // NewUoTTun returns a UoTTun proxy.
func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) { func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) {
u, err := url.Parse(s) u, err := url.Parse(s)
if err != nil { if err != nil {
@ -44,12 +44,12 @@ func NewUoTTun(s string, dialer proxy.Dialer) (*UoTTun, error) {
return p, nil return p, nil
} }
// NewUoTTunServer returns a uot tunnel server // NewUoTTunServer returns a uot tunnel server.
func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) { func NewUoTTunServer(s string, dialer proxy.Dialer) (proxy.Server, error) {
return NewUoTTun(s, dialer) return NewUoTTun(s, dialer)
} }
// ListenAndServe . // ListenAndServe listen and serve on tcp.
func (s *UoTTun) ListenAndServe() { func (s *UoTTun) ListenAndServe() {
c, err := net.ListenPacket("udp", s.addr) c, err := net.ListenPacket("udp", s.addr)
if err != nil { if err != nil {
@ -78,7 +78,7 @@ func (s *UoTTun) ListenAndServe() {
go func() { go func() {
// no remote forwarder, just a local udp forwarder // no remote forwarder, just a local udp forwarder
if urc, ok := rc.(*net.UDPConn); ok { if urc, ok := rc.(*net.UDPConn); ok {
conn.TimedCopy(c, clientAddr, urc, 2*time.Minute) conn.RelayUDP(c, clientAddr, urc, 2*time.Minute)
urc.Close() urc.Close()
return return
} }
@ -103,7 +103,7 @@ func (s *UoTTun) ListenAndServe() {
} }
} }
// Serve . // Serve is not allowed to be called directly.
func (s *UoTTun) Serve(c net.Conn) { func (s *UoTTun) Serve(c net.Conn) {
// TODO // TODO
log.F("[uottun] func Serve: can not be called directly") log.F("[uottun] func Serve: can not be called directly")

View File

@ -35,6 +35,7 @@ func NewConfFromFile(ruleFile string) (*Config, error) {
f.StringVar(&p.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr") f.StringVar(&p.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr")
f.StringVar(&p.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80") f.StringVar(&p.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
f.IntVar(&p.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)") f.IntVar(&p.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)")
f.IntVar(&p.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(seconds)")
f.StringVar(&p.StrategyConfig.IntFace, "interface", "", "source ip or source interface") f.StringVar(&p.StrategyConfig.IntFace, "interface", "", "source ip or source interface")
f.StringSliceUniqVar(&p.DNSServers, "dnsserver", nil, "remote dns server") f.StringSliceUniqVar(&p.DNSServers, "dnsserver", nil, "remote dns server")

View File

@ -15,16 +15,17 @@ import (
"github.com/nadoo/glider/proxy" "github.com/nadoo/glider/proxy"
) )
// Checker is an interface of forwarder checker // Checker is an interface of forwarder checker.
type Checker interface { type Checker interface {
Check() Check()
} }
// Config of strategy // Config is strategy config struct.
type Config struct { type Config struct {
Strategy string Strategy string
CheckWebSite string CheckWebSite string
CheckInterval int CheckInterval int
CheckTimeout int
MaxFailures int MaxFailures int
IntFace string IntFace string
} }
@ -36,7 +37,7 @@ func (p priSlice) Len() int { return len(p) }
func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() } func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() }
func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// Dialer . // Dialer is base dialer struct.
type Dialer struct { type Dialer struct {
config *Config config *Config
fwdrs priSlice fwdrs priSlice
@ -48,7 +49,7 @@ type Dialer struct {
nextForwarder func(addr string) *proxy.Forwarder nextForwarder func(addr string) *proxy.Forwarder
} }
// NewDialer returns a new strategy dialer // NewDialer returns a new strategy dialer.
func NewDialer(s []string, c *Config) proxy.Dialer { func NewDialer(s []string, c *Config) proxy.Dialer {
var fwdrs []*proxy.Forwarder var fwdrs []*proxy.Forwarder
for _, chain := range s { for _, chain := range s {
@ -111,20 +112,20 @@ func newDialer(fwdrs []*proxy.Forwarder, c *Config) *Dialer {
return d return d
} }
// Addr returns forwarder's address // Addr returns forwarder's address.
func (d *Dialer) Addr() string { return "STRATEGY" } func (d *Dialer) Addr() string { return "STRATEGY" }
// Dial connects to the address addr on the network net // Dial connects to the address addr on the network net.
func (d *Dialer) Dial(network, addr string) (net.Conn, error) { func (d *Dialer) Dial(network, addr string) (net.Conn, error) {
return d.NextDialer(addr).Dial(network, addr) return d.NextDialer(addr).Dial(network, addr)
} }
// DialUDP connects to the given address // DialUDP connects to the given address.
func (d *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) { func (d *Dialer) DialUDP(network, addr string) (pc net.PacketConn, writeTo net.Addr, err error) {
return d.NextDialer(addr).DialUDP(network, addr) return d.NextDialer(addr).DialUDP(network, addr)
} }
// NextDialer returns the next dialer // NextDialer returns the next dialer.
func (d *Dialer) NextDialer(dstAddr string) proxy.Dialer { func (d *Dialer) NextDialer(dstAddr string) proxy.Dialer {
d.mu.RLock() d.mu.RLock()
defer d.mu.RUnlock() defer d.mu.RUnlock()
@ -132,13 +133,13 @@ func (d *Dialer) NextDialer(dstAddr string) proxy.Dialer {
return d.nextForwarder(dstAddr) return d.nextForwarder(dstAddr)
} }
// Priority returns the active priority of dialer // Priority returns the active priority of dialer.
func (d *Dialer) Priority() uint32 { return atomic.LoadUint32(&d.priority) } func (d *Dialer) Priority() uint32 { return atomic.LoadUint32(&d.priority) }
// SetPriority sets the active priority of daler // SetPriority sets the active priority of daler.
func (d *Dialer) SetPriority(p uint32) { atomic.StoreUint32(&d.priority, p) } func (d *Dialer) SetPriority(p uint32) { atomic.StoreUint32(&d.priority, p) }
// initAvailable traverse d.fwdrs and init the available forwarder slice // initAvailable traverse d.fwdrs and init the available forwarder slice.
func (d *Dialer) initAvailable() { func (d *Dialer) initAvailable() {
for _, f := range d.fwdrs { for _, f := range d.fwdrs {
if f.Enabled() { if f.Enabled() {
@ -162,7 +163,7 @@ func (d *Dialer) initAvailable() {
} }
} }
// onStatusChanged will be called when fwdr's status changed // onStatusChanged will be called when fwdr's status changed.
func (d *Dialer) onStatusChanged(fwdr *proxy.Forwarder) { func (d *Dialer) onStatusChanged(fwdr *proxy.Forwarder) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
@ -189,7 +190,7 @@ func (d *Dialer) onStatusChanged(fwdr *proxy.Forwarder) {
} }
} }
// Check implements the Checker interface // Check implements the Checker interface.
func (d *Dialer) Check() { func (d *Dialer) Check() {
for i := 0; i < len(d.fwdrs); i++ { for i := 0; i < len(d.fwdrs); i++ {
go d.check(i) go d.check(i)
@ -229,11 +230,19 @@ func (d *Dialer) check(i int) {
f.Disable() f.Disable()
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err) log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, err)
} else if bytes.Equal([]byte("HTTP"), buf) { } else if bytes.Equal([]byte("HTTP"), buf) {
f.Enable()
retry = 2
readTime := time.Since(startTime) readTime := time.Since(startTime)
f.SetLatency(int64(readTime)) f.SetLatency(int64(readTime))
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime.String())
if readTime > time.Duration(d.config.CheckTimeout)*time.Second {
f.Disable()
log.F("[check] %s(%d) -> %s, DISABLED. connect timeout: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime)
} else {
retry = 2
f.Enable()
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, readTime)
}
} else { } else {
f.Disable() f.Disable()
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, buf) log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), d.config.CheckWebSite, buf)