diff --git a/cmd/gost/config.go b/cmd/gost/config.go index 52ca251..d6ba5b8 100644 --- a/cmd/gost/config.go +++ b/cmd/gost/config.go @@ -26,7 +26,7 @@ var ( chains = make(map[string]*chain.Chain) bypasses = make(map[string]bypass.Bypass) resolvers = make(map[string]resolver.Resolver) - hosts = make(map[string]*hostspkg.Hosts) + hosts = make(map[string]hostspkg.HostMapper) ) func buildService(cfg *config.Config) (services []*service.Service) { @@ -286,11 +286,11 @@ func resolverFromConfig(cfg *config.ResolverConfig) (resolver.Resolver, error) { return resolver_impl.NewResolver(nameservers) } -func hostsFromConfig(cfg *config.HostsConfig) *hostspkg.Hosts { - if cfg == nil { +func hostsFromConfig(cfg *config.HostsConfig) hostspkg.HostMapper { + if cfg == nil || len(cfg.Entries) == 0 { return nil } - hosts := &hostspkg.Hosts{} + hosts := hostspkg.NewHosts() for _, host := range cfg.Entries { if host.IP == "" || host.Hostname == "" { @@ -301,7 +301,7 @@ func hostsFromConfig(cfg *config.HostsConfig) *hostspkg.Hosts { if ip == nil { continue } - hosts.AddHost(hostspkg.NewHost(ip, host.Hostname, host.Aliases...)) + hosts.Map(ip, host.Hostname, host.Aliases...) } return hosts } diff --git a/gost.yml b/gost.yml index 9b81b5d..c2d8835 100644 --- a/gost.yml +++ b/gost.yml @@ -34,7 +34,6 @@ services: method: chacha20-ietf password: gost readTimeout: 5s - retry: 3 udp: true bufferSize: 4096 listener: @@ -52,7 +51,6 @@ services: auths: - gost:gost readTimeout: 5s - retry: 3 notls: true bind: true udp: true @@ -70,7 +68,6 @@ services: auths: - gost:gost readTimeout: 5s - retry: 3 notls: true # udpBufferSize: 1024 listener: @@ -94,7 +91,6 @@ services: chain: chain-ss metadata: readTimeout: 5s - retry: 3 listener: type: udp metadata: @@ -109,7 +105,6 @@ services: type: forward metadata: readTimeout: 5s - retry: 3 listener: type: kcp metadata: @@ -125,7 +120,6 @@ services: type: forward metadata: readTimeout: 5s - retry: 3 listener: type: rtcp metadata: @@ -145,7 +139,6 @@ services: type: forward metadata: readTimeout: 5s - retry: 3 listener: type: rudp chain: chain-socks5 @@ -325,6 +318,21 @@ hosts: - bar - baz +probeResistance: +- name: pr-code404 + type: code + value: 404 + knock: www.example.com +- name: pr-web + type: web + value: http://example.com/page.html +- name: pr-host + type: host + value: example.com:80 +- name: pr-file + type: file + value: /path/to/file + profiling: addr: ":6060" enabled: true diff --git a/pkg/chain/router.go b/pkg/chain/router.go index ca02f19..1556b0a 100644 --- a/pkg/chain/router.go +++ b/pkg/chain/router.go @@ -15,7 +15,7 @@ import ( type Router struct { Retries int Chain *Chain - Hosts *hosts.Hosts + Hosts hosts.HostMapper Resolver resolver.Resolver Logger logger.Logger } @@ -78,9 +78,11 @@ func (r *Router) resolve(ctx context.Context, addr string) (string, error) { return "", err } - if ip := r.Hosts.Lookup(host); ip != nil { - r.Logger.Debugf("hit hosts: %s -> %s", host, ip) - return net.JoinHostPort(ip.String(), port), nil + if r.Hosts != nil { + if ip := r.Hosts.Lookup(host); ip != nil { + r.Logger.Debugf("hit hosts: %s -> %s", host, ip) + return net.JoinHostPort(ip.String(), port), nil + } } if r.Resolver != nil { diff --git a/pkg/handler/http/handler.go b/pkg/handler/http/handler.go index 5ca7cae..4a580ac 100644 --- a/pkg/handler/http/handler.go +++ b/pkg/handler/http/handler.go @@ -139,22 +139,6 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt resp.Header = http.Header{} } - /* - if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) { - log.Logf("[http] %s - %s : Unauthorized to tcp connect to %s", - conn.RemoteAddr(), conn.LocalAddr(), host) - resp.StatusCode = http.StatusForbidden - - if Debug { - dump, _ := httputil.DumpResponse(resp, false) - log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(dump)) - } - - resp.Write(conn) - return - } - */ - if h.bypass != nil && h.bypass.Contains(addr) { resp.StatusCode = http.StatusForbidden diff --git a/pkg/hosts/hosts.go b/pkg/hosts/hosts.go index 893fa4f..983afbc 100644 --- a/pkg/hosts/hosts.go +++ b/pkg/hosts/hosts.go @@ -4,34 +4,37 @@ import ( "net" ) -// Host is a static mapping from hostname to IP. -type Host struct { +// HostMapper is a mapping from hostname to IP. +type HostMapper interface { + Lookup(host string) net.IP +} + +type host struct { IP net.IP Hostname string Aliases []string } -// NewHost creates a Host. -func NewHost(ip net.IP, hostname string, aliases ...string) Host { - return Host{ - IP: ip, - Hostname: hostname, - Aliases: aliases, - } -} - // Hosts is a static table lookup for hostnames. // For each host a single line should be present with the following information: // IP_address canonical_hostname [aliases...] // Fields of the entry are separated by any number of blanks and/or tab characters. // Text from a "#" character until the end of the line is a comment, and is ignored. type Hosts struct { - hosts []Host + mappings []host } -// AddHost adds host(s) to the host table. -func (h *Hosts) AddHost(host ...Host) { - h.hosts = append(h.hosts, host...) +func NewHosts() *Hosts { + return &Hosts{} +} + +// Map maps ip to hostname or aliases. +func (h *Hosts) Map(ip net.IP, hostname string, aliases ...string) { + h.mappings = append(h.mappings, host{ + IP: ip, + Hostname: hostname, + Aliases: aliases, + }) } // Lookup searches the IP address corresponds to the given host from the host table. @@ -40,7 +43,7 @@ func (h *Hosts) Lookup(host string) (ip net.IP) { return } - for _, h := range h.hosts { + for _, h := range h.mappings { if h.Hostname == host { ip = h.IP break diff --git a/pkg/internal/util/resolver/cache.go b/pkg/internal/util/resolver/cache.go index eef779e..ac38466 100644 --- a/pkg/internal/util/resolver/cache.go +++ b/pkg/internal/util/resolver/cache.go @@ -51,22 +51,12 @@ func (c *Cache) Load(key CacheKey) *dns.Msg { return nil } - elapsed := time.Since(item.ts) - if item.ttl > 0 { - if elapsed > item.ttl { - c.m.Delete(key) - return nil - } - } else { - for _, rr := range item.msg.Answer { - if elapsed > time.Duration(rr.Header().Ttl)*time.Second { - c.m.Delete(key) - return nil - } - } + if time.Since(item.ts) > item.ttl { + c.m.Delete(key) + return nil } - c.logger.Debugf("resolver cache hit %s", key) + c.logger.Debugf("resolver cache hit: %s", key) return item.msg.Copy() } @@ -76,11 +66,23 @@ func (c *Cache) Store(key CacheKey, mr *dns.Msg, ttl time.Duration) { return } + if ttl == 0 { + for _, answer := range mr.Answer { + v := time.Duration(answer.Header().Ttl) * time.Second + if ttl == 0 || ttl > v { + ttl = v + } + } + } + if ttl == 0 { + ttl = 30 * time.Second + } + c.m.Store(key, &cacheItem{ msg: mr.Copy(), ts: time.Now(), ttl: ttl, }) - c.logger.Debugf("resolver cache store %s", key) + c.logger.Debugf("resolver cache store: %s, ttl: %v", key, ttl) }