Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6b4a84ee6e | ||
|
d49ec87c17 | ||
|
6799cc5a95 | ||
|
4ac048a8a2 | ||
|
de4a896004 | ||
|
fd0d28e815 | ||
|
97ff9b846b | ||
|
7c16e3e519 | ||
|
145d45df4e |
10
.github/workflows/buildx.yaml
vendored
10
.github/workflows/buildx.yaml
vendored
@ -19,8 +19,7 @@ jobs:
|
||||
echo ::set-output name=version::snapshot
|
||||
fi
|
||||
|
||||
echo ::set-output name=build_date::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||
echo ::set-output name=docker_platforms::linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/386
|
||||
echo ::set-output name=docker_platforms::linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386
|
||||
echo ::set-output name=docker_image::${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}
|
||||
|
||||
# https://github.com/crazy-max/ghaction-docker-buildx
|
||||
@ -36,7 +35,6 @@ jobs:
|
||||
echo git_ref=$GITHUB_REF
|
||||
echo git_sha=$GITHUB_SHA
|
||||
echo version=${{ steps.prepare.outputs.version }}
|
||||
echo date=${{ steps.prepare.outputs.build_date }}
|
||||
echo image=${{ steps.prepare.outputs.docker_image }}
|
||||
echo platforms=${{ steps.prepare.outputs.docker_platforms }}
|
||||
echo avail_platforms=${{ steps.buildx.outputs.platforms }}
|
||||
@ -50,9 +48,6 @@ jobs:
|
||||
docker buildx build \
|
||||
--platform ${{ steps.prepare.outputs.docker_platforms }} \
|
||||
--output "type=image,push=false" \
|
||||
--build-arg "VERSION=${{ steps.prepare.outputs.version }}" \
|
||||
--build-arg "BUILD_DATE=${{ steps.prepare.outputs.build_date }}" \
|
||||
--build-arg "VCS_REF=${GITHUB_SHA::8}" \
|
||||
--tag "${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }}" \
|
||||
--file Dockerfile .
|
||||
|
||||
@ -69,9 +64,6 @@ jobs:
|
||||
docker buildx build \
|
||||
--platform ${{ steps.prepare.outputs.docker_platforms }} \
|
||||
--output "type=image,push=true" \
|
||||
--build-arg "VERSION=${{ steps.prepare.outputs.version }}" \
|
||||
--build-arg "BUILD_DATE=${{ steps.prepare.outputs.build_date }}" \
|
||||
--build-arg "VCS_REF=${GITHUB_SHA::8}" \
|
||||
--tag "${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }}" \
|
||||
--file Dockerfile .
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
FROM golang:1-alpine as builder
|
||||
|
||||
RUN apk add --no-cache musl-dev git gcc
|
||||
RUN apk add --no-cache musl-dev gcc
|
||||
|
||||
ADD . /src
|
||||
|
||||
|
298
bypass.go
298
bypass.go
@ -1,298 +0,0 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
glob "github.com/gobwas/glob"
|
||||
)
|
||||
|
||||
// Matcher is a generic pattern matcher,
|
||||
// it gives the match result of the given pattern for specific v.
|
||||
type Matcher interface {
|
||||
Match(v string) bool
|
||||
String() string
|
||||
}
|
||||
|
||||
// NewMatcher creates a Matcher for the given pattern.
|
||||
// The acutal Matcher depends on the pattern:
|
||||
// IP Matcher if pattern is a valid IP address.
|
||||
// CIDR Matcher if pattern is a valid CIDR address.
|
||||
// Domain Matcher if both of the above are not.
|
||||
func NewMatcher(pattern string) Matcher {
|
||||
if pattern == "" {
|
||||
return nil
|
||||
}
|
||||
if ip := net.ParseIP(pattern); ip != nil {
|
||||
return IPMatcher(ip)
|
||||
}
|
||||
if _, inet, err := net.ParseCIDR(pattern); err == nil {
|
||||
return CIDRMatcher(inet)
|
||||
}
|
||||
return DomainMatcher(pattern)
|
||||
}
|
||||
|
||||
type ipMatcher struct {
|
||||
ip net.IP
|
||||
}
|
||||
|
||||
// IPMatcher creates a Matcher for a specific IP address.
|
||||
func IPMatcher(ip net.IP) Matcher {
|
||||
return &ipMatcher{
|
||||
ip: ip,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ipMatcher) Match(ip string) bool {
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
return m.ip.Equal(net.ParseIP(ip))
|
||||
}
|
||||
|
||||
func (m *ipMatcher) String() string {
|
||||
return "ip " + m.ip.String()
|
||||
}
|
||||
|
||||
type cidrMatcher struct {
|
||||
ipNet *net.IPNet
|
||||
}
|
||||
|
||||
// CIDRMatcher creates a Matcher for a specific CIDR notation IP address.
|
||||
func CIDRMatcher(inet *net.IPNet) Matcher {
|
||||
return &cidrMatcher{
|
||||
ipNet: inet,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *cidrMatcher) Match(ip string) bool {
|
||||
if m == nil || m.ipNet == nil {
|
||||
return false
|
||||
}
|
||||
return m.ipNet.Contains(net.ParseIP(ip))
|
||||
}
|
||||
|
||||
func (m *cidrMatcher) String() string {
|
||||
return "cidr " + m.ipNet.String()
|
||||
}
|
||||
|
||||
type domainMatcher struct {
|
||||
pattern string
|
||||
glob glob.Glob
|
||||
}
|
||||
|
||||
// DomainMatcher creates a Matcher for a specific domain pattern,
|
||||
// the pattern can be a plain domain such as 'example.com',
|
||||
// a wildcard such as '*.exmaple.com' or a special wildcard '.example.com'.
|
||||
func DomainMatcher(pattern string) Matcher {
|
||||
p := pattern
|
||||
if strings.HasPrefix(pattern, ".") {
|
||||
p = pattern[1:] // trim the prefix '.'
|
||||
pattern = "*" + p
|
||||
}
|
||||
return &domainMatcher{
|
||||
pattern: p,
|
||||
glob: glob.MustCompile(pattern),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *domainMatcher) Match(domain string) bool {
|
||||
if m == nil || m.glob == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if domain == m.pattern {
|
||||
return true
|
||||
}
|
||||
return m.glob.Match(domain)
|
||||
}
|
||||
|
||||
func (m *domainMatcher) String() string {
|
||||
return "domain " + m.pattern
|
||||
}
|
||||
|
||||
// Bypass is a filter for address (IP or domain).
|
||||
// It contains a list of matchers.
|
||||
type Bypass struct {
|
||||
matchers []Matcher
|
||||
period time.Duration // the period for live reloading
|
||||
reversed bool
|
||||
stopped chan struct{}
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
// NewBypass creates and initializes a new Bypass using matchers as its match rules.
|
||||
// The rules will be reversed if the reversed is true.
|
||||
func NewBypass(reversed bool, matchers ...Matcher) *Bypass {
|
||||
return &Bypass{
|
||||
matchers: matchers,
|
||||
reversed: reversed,
|
||||
stopped: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// NewBypassPatterns creates and initializes a new Bypass using matcher patterns as its match rules.
|
||||
// The rules will be reversed if the reverse is true.
|
||||
func NewBypassPatterns(reversed bool, patterns ...string) *Bypass {
|
||||
var matchers []Matcher
|
||||
for _, pattern := range patterns {
|
||||
if m := NewMatcher(pattern); m != nil {
|
||||
matchers = append(matchers, m)
|
||||
}
|
||||
}
|
||||
bp := NewBypass(reversed)
|
||||
bp.AddMatchers(matchers...)
|
||||
return bp
|
||||
}
|
||||
|
||||
// Contains reports whether the bypass includes addr.
|
||||
func (bp *Bypass) Contains(addr string) bool {
|
||||
if bp == nil || addr == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// try to strip the port
|
||||
if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" {
|
||||
if p, _ := strconv.Atoi(port); p > 0 { // port is valid
|
||||
addr = host
|
||||
}
|
||||
}
|
||||
|
||||
bp.mux.RLock()
|
||||
defer bp.mux.RUnlock()
|
||||
|
||||
if len(bp.matchers) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var matched bool
|
||||
for _, matcher := range bp.matchers {
|
||||
if matcher == nil {
|
||||
continue
|
||||
}
|
||||
if matcher.Match(addr) {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return !bp.reversed && matched ||
|
||||
bp.reversed && !matched
|
||||
}
|
||||
|
||||
// AddMatchers appends matchers to the bypass matcher list.
|
||||
func (bp *Bypass) AddMatchers(matchers ...Matcher) {
|
||||
bp.mux.Lock()
|
||||
defer bp.mux.Unlock()
|
||||
|
||||
bp.matchers = append(bp.matchers, matchers...)
|
||||
}
|
||||
|
||||
// Matchers return the bypass matcher list.
|
||||
func (bp *Bypass) Matchers() []Matcher {
|
||||
bp.mux.RLock()
|
||||
defer bp.mux.RUnlock()
|
||||
|
||||
return bp.matchers
|
||||
}
|
||||
|
||||
// Reversed reports whether the rules of the bypass are reversed.
|
||||
func (bp *Bypass) Reversed() bool {
|
||||
bp.mux.RLock()
|
||||
defer bp.mux.RUnlock()
|
||||
|
||||
return bp.reversed
|
||||
}
|
||||
|
||||
// Reload parses config from r, then live reloads the bypass.
|
||||
func (bp *Bypass) Reload(r io.Reader) error {
|
||||
var matchers []Matcher
|
||||
var period time.Duration
|
||||
var reversed bool
|
||||
|
||||
if r == nil || bp.Stopped() {
|
||||
return nil
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
ss := splitLine(line)
|
||||
if len(ss) == 0 {
|
||||
continue
|
||||
}
|
||||
switch ss[0] {
|
||||
case "reload": // reload option
|
||||
if len(ss) > 1 {
|
||||
period, _ = time.ParseDuration(ss[1])
|
||||
}
|
||||
case "reverse": // reverse option
|
||||
if len(ss) > 1 {
|
||||
reversed, _ = strconv.ParseBool(ss[1])
|
||||
}
|
||||
default:
|
||||
matchers = append(matchers, NewMatcher(ss[0]))
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bp.mux.Lock()
|
||||
defer bp.mux.Unlock()
|
||||
|
||||
bp.matchers = matchers
|
||||
bp.period = period
|
||||
bp.reversed = reversed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Period returns the reload period.
|
||||
func (bp *Bypass) Period() time.Duration {
|
||||
if bp.Stopped() {
|
||||
return -1
|
||||
}
|
||||
|
||||
bp.mux.RLock()
|
||||
defer bp.mux.RUnlock()
|
||||
|
||||
return bp.period
|
||||
}
|
||||
|
||||
// Stop stops reloading.
|
||||
func (bp *Bypass) Stop() {
|
||||
select {
|
||||
case <-bp.stopped:
|
||||
default:
|
||||
close(bp.stopped)
|
||||
}
|
||||
}
|
||||
|
||||
// Stopped checks whether the reloader is stopped.
|
||||
func (bp *Bypass) Stopped() bool {
|
||||
select {
|
||||
case <-bp.stopped:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (bp *Bypass) String() string {
|
||||
b := &bytes.Buffer{}
|
||||
fmt.Fprintf(b, "reversed: %v\n", bp.Reversed())
|
||||
fmt.Fprintf(b, "reload: %v\n", bp.Period())
|
||||
for _, m := range bp.Matchers() {
|
||||
b.WriteString(m.String())
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
return b.String()
|
||||
}
|
303
bypass_test.go
303
bypass_test.go
@ -1,303 +0,0 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var bypassContainTests = []struct {
|
||||
patterns []string
|
||||
reversed bool
|
||||
addr string
|
||||
bypassed bool
|
||||
}{
|
||||
// empty pattern
|
||||
{[]string{""}, false, "", false},
|
||||
{[]string{""}, false, "192.168.1.1", false},
|
||||
{[]string{""}, true, "", false},
|
||||
{[]string{""}, true, "192.168.1.1", false},
|
||||
|
||||
// IP address
|
||||
{[]string{"192.168.1.1"}, false, "192.168.1.1", true},
|
||||
{[]string{"192.168.1.1"}, true, "192.168.1.1", false},
|
||||
{[]string{"192.168.1.1"}, false, "192.168.1.2", false},
|
||||
{[]string{"192.168.1.1"}, true, "192.168.1.2", true},
|
||||
{[]string{"0.0.0.0"}, false, "0.0.0.0", true},
|
||||
{[]string{"0.0.0.0"}, true, "0.0.0.0", false},
|
||||
|
||||
// CIDR address
|
||||
{[]string{"192.168.1.0/0"}, false, "1.2.3.4", true},
|
||||
{[]string{"192.168.1.0/0"}, true, "1.2.3.4", false},
|
||||
{[]string{"192.168.1.0/8"}, false, "192.1.0.255", true},
|
||||
{[]string{"192.168.1.0/8"}, true, "192.1.0.255", false},
|
||||
{[]string{"192.168.1.0/8"}, false, "191.1.0.255", false},
|
||||
{[]string{"192.168.1.0/8"}, true, "191.1.0.255", true},
|
||||
{[]string{"192.168.1.0/16"}, false, "192.168.0.255", true},
|
||||
{[]string{"192.168.1.0/16"}, true, "192.168.0.255", false},
|
||||
{[]string{"192.168.1.0/16"}, false, "192.0.1.255", false},
|
||||
{[]string{"192.168.1.0/16"}, true, "192.0.0.255", true},
|
||||
{[]string{"192.168.1.0/24"}, false, "192.168.1.255", true},
|
||||
{[]string{"192.168.1.0/24"}, true, "192.168.1.255", false},
|
||||
{[]string{"192.168.1.0/24"}, false, "192.168.0.255", false},
|
||||
{[]string{"192.168.1.0/24"}, true, "192.168.0.255", true},
|
||||
{[]string{"192.168.1.1/32"}, false, "192.168.1.1", true},
|
||||
{[]string{"192.168.1.1/32"}, true, "192.168.1.1", false},
|
||||
{[]string{"192.168.1.1/32"}, false, "192.168.1.2", false},
|
||||
{[]string{"192.168.1.1/32"}, true, "192.168.1.2", true},
|
||||
|
||||
// plain domain
|
||||
{[]string{"www.example.com"}, false, "www.example.com", true},
|
||||
{[]string{"www.example.com"}, true, "www.example.com", false},
|
||||
{[]string{"http://www.example.com"}, false, "http://www.example.com", true},
|
||||
{[]string{"http://www.example.com"}, true, "http://www.example.com", false},
|
||||
{[]string{"http://www.example.com"}, false, "http://example.com", false},
|
||||
{[]string{"http://www.example.com"}, true, "http://example.com", true},
|
||||
{[]string{"www.example.com"}, false, "example.com", false},
|
||||
{[]string{"www.example.com"}, true, "example.com", true},
|
||||
|
||||
// host:port
|
||||
{[]string{"192.168.1.1"}, false, "192.168.1.1:80", true},
|
||||
{[]string{"192.168.1.1"}, true, "192.168.1.1:80", false},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1", false},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1", true},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1:80", false},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1:80", true},
|
||||
{[]string{"192.168.1.1:80"}, false, "192.168.1.1:8080", false},
|
||||
{[]string{"192.168.1.1:80"}, true, "192.168.1.1:8080", true},
|
||||
|
||||
{[]string{"example.com"}, false, "example.com:80", true},
|
||||
{[]string{"example.com"}, true, "example.com:80", false},
|
||||
{[]string{"example.com:80"}, false, "example.com", false},
|
||||
{[]string{"example.com:80"}, true, "example.com", true},
|
||||
{[]string{"example.com:80"}, false, "example.com:80", false},
|
||||
{[]string{"example.com:80"}, true, "example.com:80", true},
|
||||
{[]string{"example.com:80"}, false, "example.com:8080", false},
|
||||
{[]string{"example.com:80"}, true, "example.com:8080", true},
|
||||
|
||||
// domain wildcard
|
||||
|
||||
{[]string{"*"}, false, "", false},
|
||||
{[]string{"*"}, false, "192.168.1.1", true},
|
||||
{[]string{"*"}, false, "192.168.0.0/16", true},
|
||||
{[]string{"*"}, false, "http://example.com", true},
|
||||
{[]string{"*"}, false, "example.com:80", true},
|
||||
{[]string{"*"}, true, "", false},
|
||||
{[]string{"*"}, true, "192.168.1.1", false},
|
||||
{[]string{"*"}, true, "192.168.0.0/16", false},
|
||||
{[]string{"*"}, true, "http://example.com", false},
|
||||
{[]string{"*"}, true, "example.com:80", false},
|
||||
|
||||
// sub-domain
|
||||
{[]string{"*.example.com"}, false, "example.com", false},
|
||||
{[]string{"*.example.com"}, false, "http://example.com", false},
|
||||
{[]string{"*.example.com"}, false, "www.example.com", true},
|
||||
{[]string{"*.example.com"}, false, "http://www.example.com", true},
|
||||
{[]string{"*.example.com"}, false, "abc.def.example.com", true},
|
||||
|
||||
{[]string{"*.*.example.com"}, false, "example.com", false},
|
||||
{[]string{"*.*.example.com"}, false, "www.example.com", false},
|
||||
{[]string{"*.*.example.com"}, false, "abc.def.example.com", true},
|
||||
{[]string{"*.*.example.com"}, false, "abc.def.ghi.example.com", true},
|
||||
|
||||
{[]string{"**.example.com"}, false, "example.com", false},
|
||||
{[]string{"**.example.com"}, false, "www.example.com", true},
|
||||
{[]string{"**.example.com"}, false, "abc.def.ghi.example.com", true},
|
||||
|
||||
// prefix wildcard
|
||||
{[]string{"*example.com"}, false, "example.com", true},
|
||||
{[]string{"*example.com"}, false, "www.example.com", true},
|
||||
{[]string{"*example.com"}, false, "abc.defexample.com", true},
|
||||
{[]string{"*example.com"}, false, "abc.def-example.com", true},
|
||||
{[]string{"*example.com"}, false, "abc.def.example.com", true},
|
||||
{[]string{"*example.com"}, false, "http://www.example.com", true},
|
||||
{[]string{"*example.com"}, false, "e-xample.com", false},
|
||||
|
||||
{[]string{"http://*.example.com"}, false, "example.com", false},
|
||||
{[]string{"http://*.example.com"}, false, "http://example.com", false},
|
||||
{[]string{"http://*.example.com"}, false, "http://www.example.com", true},
|
||||
{[]string{"http://*.example.com"}, false, "https://www.example.com", false},
|
||||
{[]string{"http://*.example.com"}, false, "http://abc.def.example.com", true},
|
||||
|
||||
{[]string{"www.*.com"}, false, "www.example.com", true},
|
||||
{[]string{"www.*.com"}, false, "www.abc.def.com", true},
|
||||
|
||||
{[]string{"www.*.*.com"}, false, "www.example.com", false},
|
||||
{[]string{"www.*.*.com"}, false, "www.abc.def.com", true},
|
||||
{[]string{"www.*.*.com"}, false, "www.abc.def.ghi.com", true},
|
||||
|
||||
{[]string{"www.*example*.com"}, false, "www.example.com", true},
|
||||
{[]string{"www.*example*.com"}, false, "www.abc.example.def.com", true},
|
||||
{[]string{"www.*example*.com"}, false, "www.e-xample.com", false},
|
||||
|
||||
{[]string{"www.example.*"}, false, "www.example.com", true},
|
||||
{[]string{"www.example.*"}, false, "www.example.io", true},
|
||||
{[]string{"www.example.*"}, false, "www.example.com.cn", true},
|
||||
|
||||
{[]string{".example.com"}, false, "www.example.com", true},
|
||||
{[]string{".example.com"}, false, "example.com", true},
|
||||
{[]string{".example.com"}, false, "www.example.com.cn", false},
|
||||
|
||||
{[]string{"example.com*"}, false, "example.com", true},
|
||||
{[]string{"example.com:*"}, false, "example.com", false},
|
||||
{[]string{"example.com:*"}, false, "example.com:80", false},
|
||||
{[]string{"example.com:*"}, false, "example.com:8080", false},
|
||||
{[]string{"example.com:*"}, false, "example.com:http", true},
|
||||
{[]string{"example.com:*"}, false, "http://example.com:80", false},
|
||||
|
||||
{[]string{"*example.com*"}, false, "example.com:80", true},
|
||||
{[]string{"*example.com:*"}, false, "example.com:80", false},
|
||||
|
||||
{[]string{".example.com:*"}, false, "www.example.com", false},
|
||||
{[]string{".example.com:*"}, false, "http://www.example.com", false},
|
||||
{[]string{".example.com:*"}, false, "example.com:80", false},
|
||||
{[]string{".example.com:*"}, false, "www.example.com:8080", false},
|
||||
{[]string{".example.com:*"}, false, "http://www.example.com:80", true},
|
||||
}
|
||||
|
||||
func TestBypassContains(t *testing.T) {
|
||||
for i, tc := range bypassContainTests {
|
||||
tc := tc
|
||||
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
|
||||
bp := NewBypassPatterns(tc.reversed, tc.patterns...)
|
||||
if bp.Contains(tc.addr) != tc.bypassed {
|
||||
t.Errorf("#%d test failed: %v, %s", i, tc.patterns, tc.addr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var bypassReloadTests = []struct {
|
||||
r io.Reader
|
||||
|
||||
reversed bool
|
||||
period time.Duration
|
||||
|
||||
addr string
|
||||
bypassed bool
|
||||
stopped bool
|
||||
}{
|
||||
{
|
||||
r: nil,
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "192.168.1.1",
|
||||
bypassed: false,
|
||||
stopped: false,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString(""),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "192.168.1.1",
|
||||
bypassed: false,
|
||||
stopped: false,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("reverse true\nreload 10s"),
|
||||
reversed: true,
|
||||
period: 10 * time.Second,
|
||||
addr: "192.168.1.1",
|
||||
bypassed: false,
|
||||
stopped: false,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("reverse false\nreload 10s\n192.168.1.1"),
|
||||
reversed: false,
|
||||
period: 10 * time.Second,
|
||||
addr: "192.168.1.1",
|
||||
bypassed: true,
|
||||
stopped: false,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reverse true\n#reload 10s\n192.168.0.0/16"),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "192.168.10.2",
|
||||
bypassed: true,
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reverse true\n#reload 10s\n192.168.1.0/24 #comment"),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "192.168.10.2",
|
||||
bypassed: false,
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("reverse false\nreload 10s\n192.168.1.1\n#example.com"),
|
||||
reversed: false,
|
||||
period: 10 * time.Second,
|
||||
addr: "example.com",
|
||||
bypassed: false,
|
||||
stopped: false,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reverse true\n#reload 10s\n192.168.1.1\n#example.com"),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "192.168.1.1",
|
||||
bypassed: true,
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reverse true\n#reload 10s\nexample.com #comment"),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "example.com",
|
||||
bypassed: true,
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reverse true\n#reload 10s\n.example.com"),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "example.com",
|
||||
bypassed: true,
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reverse true\n#reload 10s\n*.example.com"),
|
||||
reversed: false,
|
||||
period: 0,
|
||||
addr: "example.com",
|
||||
bypassed: false,
|
||||
stopped: true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestByapssReload(t *testing.T) {
|
||||
for i, tc := range bypassReloadTests {
|
||||
bp := NewBypass(false)
|
||||
if err := bp.Reload(tc.r); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Log(bp.String())
|
||||
|
||||
if bp.Reversed() != tc.reversed {
|
||||
t.Errorf("#%d test failed: reversed value should be %v, got %v",
|
||||
i, tc.reversed, bp.reversed)
|
||||
}
|
||||
if bp.Period() != tc.period {
|
||||
t.Errorf("#%d test failed: period value should be %v, got %v",
|
||||
i, tc.period, bp.Period())
|
||||
}
|
||||
if bp.Contains(tc.addr) != tc.bypassed {
|
||||
t.Errorf("#%d test failed: %v, %s", i, bp.reversed, tc.addr)
|
||||
}
|
||||
if tc.stopped {
|
||||
bp.Stop()
|
||||
if bp.Period() >= 0 {
|
||||
t.Errorf("period of the stopped reloader should be minus value")
|
||||
}
|
||||
bp.Stop()
|
||||
}
|
||||
if bp.Stopped() != tc.stopped {
|
||||
t.Errorf("#%d test failed: stopped value should be %v, got %v",
|
||||
i, tc.stopped, bp.Stopped())
|
||||
}
|
||||
}
|
||||
}
|
17
chain.go
17
chain.go
@ -6,7 +6,8 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/hosts"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -179,14 +180,16 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
func (*Chain) resolve(addr string, resolver Resolver, hosts *Hosts) string {
|
||||
func (*Chain) resolve(addr string, resolver Resolver, hosts hosts.Hosts) string {
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return addr
|
||||
}
|
||||
|
||||
if ip := hosts.Lookup(host); ip != nil {
|
||||
return net.JoinHostPort(ip.String(), port)
|
||||
if hosts != nil {
|
||||
if ip := hosts.Lookup(host); ip != nil {
|
||||
return net.JoinHostPort(ip.String(), port)
|
||||
}
|
||||
}
|
||||
if resolver != nil {
|
||||
ips, err := resolver.Resolve(host)
|
||||
@ -302,7 +305,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if node.Bypass.Contains(addr) {
|
||||
if node.Bypasser != nil && node.Bypasser.Bypass(addr) {
|
||||
break
|
||||
}
|
||||
|
||||
@ -326,7 +329,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) {
|
||||
type ChainOptions struct {
|
||||
Retries int
|
||||
Timeout time.Duration
|
||||
Hosts *Hosts
|
||||
Hosts hosts.Hosts
|
||||
Resolver Resolver
|
||||
}
|
||||
|
||||
@ -348,7 +351,7 @@ func TimeoutChainOption(timeout time.Duration) ChainOption {
|
||||
}
|
||||
|
||||
// HostsChainOption specifies the hosts used by Chain.Dial.
|
||||
func HostsChainOption(hosts *Hosts) ChainOption {
|
||||
func HostsChainOption(hosts hosts.Hosts) ChainOption {
|
||||
return func(opts *ChainOptions) {
|
||||
opts.Hosts = hosts
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ type Transporter interface {
|
||||
type DialOptions struct {
|
||||
Timeout time.Duration
|
||||
Chain *Chain
|
||||
Host string
|
||||
}
|
||||
|
||||
// DialOption allows a common way to set DialOptions.
|
||||
@ -102,6 +103,13 @@ func ChainDialOption(chain *Chain) DialOption {
|
||||
}
|
||||
}
|
||||
|
||||
// HostDialOption specifies the host used by Transporter.Dial
|
||||
func HostDialOption(host string) DialOption {
|
||||
return func(opts *DialOptions) {
|
||||
opts.Host = host
|
||||
}
|
||||
}
|
||||
|
||||
// HandshakeOptions describes the options for handshake.
|
||||
type HandshakeOptions struct {
|
||||
Addr string
|
||||
|
5
cmd/gost/bypass.txt
Normal file
5
cmd/gost/bypass.txt
Normal file
@ -0,0 +1,5 @@
|
||||
reload 3s
|
||||
|
||||
reverse true
|
||||
|
||||
.baidu.com
|
@ -13,6 +13,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ginuerzh/gost"
|
||||
"github.com/go-gost/bypass"
|
||||
"github.com/go-gost/hosts"
|
||||
"github.com/go-gost/reloader"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -130,7 +133,7 @@ func parseAuthenticator(s string) (gost.Authenticator, error) {
|
||||
au := gost.NewLocalAuthenticator(nil)
|
||||
au.Reload(f)
|
||||
|
||||
go gost.PeriodReload(au, s)
|
||||
go reloader.PeriodReload(au, s)
|
||||
|
||||
return au, nil
|
||||
}
|
||||
@ -174,11 +177,11 @@ func parseIP(s string, port string) (ips []string) {
|
||||
return
|
||||
}
|
||||
|
||||
func parseBypass(s string) *gost.Bypass {
|
||||
func parseBypasser(s string) bypass.Bypasser {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
var matchers []gost.Matcher
|
||||
var matchers []bypass.Matcher
|
||||
var reversed bool
|
||||
if strings.HasPrefix(s, "~") {
|
||||
reversed = true
|
||||
@ -192,15 +195,17 @@ func parseBypass(s string) *gost.Bypass {
|
||||
if s == "" {
|
||||
continue
|
||||
}
|
||||
matchers = append(matchers, gost.NewMatcher(s))
|
||||
matchers = append(matchers, bypass.NewMatcher(s))
|
||||
}
|
||||
return gost.NewBypass(reversed, matchers...)
|
||||
return bypass.NewBypasser(reversed, matchers...)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
bp := gost.NewBypass(reversed)
|
||||
bp.Reload(f)
|
||||
go gost.PeriodReload(bp, s)
|
||||
bp := bypass.NewBypasser(reversed)
|
||||
if r, ok := bp.(reloader.Reloader); ok {
|
||||
r.Reload(f)
|
||||
go reloader.PeriodReload(r, s)
|
||||
}
|
||||
|
||||
return bp
|
||||
}
|
||||
@ -257,24 +262,25 @@ func parseResolver(cfg string) gost.Resolver {
|
||||
resolver := gost.NewResolver(0)
|
||||
resolver.Reload(f)
|
||||
|
||||
go gost.PeriodReload(resolver, cfg)
|
||||
go reloader.PeriodReload(resolver, cfg)
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
func parseHosts(s string) *gost.Hosts {
|
||||
func parseHosts(s string) hosts.Hosts {
|
||||
f, err := os.Open(s)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
hosts := gost.NewHosts()
|
||||
hosts.Reload(f)
|
||||
hsts := hosts.NewHosts()
|
||||
if r, ok := hsts.(reloader.Reloader); ok {
|
||||
r.Reload(f)
|
||||
go reloader.PeriodReload(r, s)
|
||||
}
|
||||
|
||||
go gost.PeriodReload(hosts, s)
|
||||
|
||||
return hosts
|
||||
return hsts
|
||||
}
|
||||
|
||||
func parseIPRoutes(s string) (routes []gost.IPRoute) {
|
||||
|
@ -5,14 +5,14 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
stdlog "log"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
_ "net/http/pprof"
|
||||
|
||||
"github.com/ginuerzh/gost"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -23,7 +23,8 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
gost.SetLogger(&gost.LogLogger{})
|
||||
stdlog.SetFlags(stdlog.LstdFlags | stdlog.Lshortfile)
|
||||
gost.SetLogger(&log.StdLogger{})
|
||||
|
||||
var (
|
||||
printVersion bool
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ginuerzh/gost"
|
||||
"github.com/go-gost/reloader"
|
||||
)
|
||||
|
||||
type peerConfig struct {
|
||||
@ -74,8 +75,8 @@ func (cfg *peerConfig) Reload(r io.Reader) error {
|
||||
|
||||
nodes := group.SetNodes(gNodes...)
|
||||
for _, node := range nodes[len(cfg.baseNodes):] {
|
||||
if node.Bypass != nil {
|
||||
node.Bypass.Stop() // clear the old nodes
|
||||
if s, ok := node.Bypasser.(reloader.Stoppable); ok {
|
||||
s.Stop() // clear the old nodes
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ginuerzh/gost"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/hosts"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/go-gost/reloader"
|
||||
)
|
||||
|
||||
type stringList []string
|
||||
@ -76,7 +78,7 @@ func (r *route) parseChain() (*gost.Chain, error) {
|
||||
peerCfg.Reload(f)
|
||||
f.Close()
|
||||
|
||||
go gost.PeriodReload(peerCfg, cfg)
|
||||
go reloader.PeriodReload(peerCfg, cfg)
|
||||
}
|
||||
|
||||
chain.AddNodeGroup(ngroup)
|
||||
@ -234,8 +236,14 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
connector = gost.AutoConnector(node.User)
|
||||
}
|
||||
|
||||
host := node.Get("host")
|
||||
if host == "" {
|
||||
host = node.Host
|
||||
}
|
||||
|
||||
node.DialOptions = append(node.DialOptions,
|
||||
gost.TimeoutDialOption(timeout),
|
||||
gost.HostDialOption(host),
|
||||
)
|
||||
|
||||
node.ConnectOptions = []gost.ConnectOption{
|
||||
@ -244,11 +252,6 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
gost.NoDelayConnectOption(node.GetBool("nodelay")),
|
||||
}
|
||||
|
||||
host := node.Get("host")
|
||||
if host == "" {
|
||||
host = node.Host
|
||||
}
|
||||
|
||||
sshConfig := &gost.SSHConfig{}
|
||||
if s := node.Get("ssh_key"); s != "" {
|
||||
key, err := gost.ParseSSHKeyFile(s)
|
||||
@ -273,7 +276,7 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) {
|
||||
Transporter: tr,
|
||||
}
|
||||
|
||||
node.Bypass = parseBypass(node.Get("bypass"))
|
||||
node.Bypasser = parseBypasser(node.Get("bypass"))
|
||||
|
||||
ips := parseIP(node.Get("ip"), sport)
|
||||
for _, ip := range ips {
|
||||
@ -579,7 +582,7 @@ func (r *route) GenRouters() ([]router, error) {
|
||||
}
|
||||
}
|
||||
|
||||
node.Bypass = parseBypass(node.Get("bypass"))
|
||||
node.Bypasser = parseBypasser(node.Get("bypass"))
|
||||
hosts := parseHosts(node.Get("hosts"))
|
||||
ips := parseIP(node.Get("ip"), "")
|
||||
|
||||
@ -605,7 +608,7 @@ func (r *route) GenRouters() ([]router, error) {
|
||||
gost.StrategyHandlerOption(gost.NewStrategy(node.Get("strategy"))),
|
||||
gost.MaxFailsHandlerOption(node.GetInt("max_fails")),
|
||||
gost.FailTimeoutHandlerOption(node.GetDuration("fail_timeout")),
|
||||
gost.BypassHandlerOption(node.Bypass),
|
||||
gost.BypasserHandlerOption(node.Bypasser),
|
||||
gost.ResolverHandlerOption(resolver),
|
||||
gost.HostsHandlerOption(hosts),
|
||||
gost.RetryHandlerOption(node.GetInt("retry")), // override the global retry option.
|
||||
@ -638,7 +641,7 @@ type router struct {
|
||||
handler gost.Handler
|
||||
chain *gost.Chain
|
||||
resolver gost.Resolver
|
||||
hosts *gost.Hosts
|
||||
hosts hosts.Hosts
|
||||
}
|
||||
|
||||
func (r *router) Serve() error {
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
7
dns.go
7
dns.go
@ -14,7 +14,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -59,8 +60,8 @@ func (h *dnsHandler) Init(opts ...HandlerOption) {
|
||||
func (h *dnsHandler) Handle(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, err := conn.Read(b)
|
||||
if err != nil {
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
smux "gopkg.in/xtaci/smux.v1"
|
||||
)
|
||||
|
||||
|
2
ftcp.go
2
ftcp.go
@ -5,7 +5,7 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/xtaci/tcpraw"
|
||||
)
|
||||
|
||||
|
7
go.mod
7
go.mod
@ -15,9 +15,12 @@ require (
|
||||
github.com/ginuerzh/gosocks4 v0.0.1
|
||||
github.com/ginuerzh/gosocks5 v0.2.0
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796
|
||||
github.com/go-gost/bpool v1.0.0
|
||||
github.com/go-gost/bypass v1.0.0
|
||||
github.com/go-gost/hosts v1.0.0
|
||||
github.com/go-gost/log v1.0.0
|
||||
github.com/go-gost/relay v0.1.0
|
||||
github.com/go-log/log v0.1.0
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/go-gost/reloader v1.1.0
|
||||
github.com/golang/mock v1.2.0 // indirect
|
||||
github.com/google/gopacket v1.1.17 // indirect
|
||||
github.com/gorilla/websocket v1.4.0 // indirect
|
||||
|
31
go.sum
31
go.sum
@ -16,7 +16,6 @@ github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitf
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
|
||||
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/dchest/siphash v1.2.0 h1:YWOShuhvg0GqbQpMa60QlCGtEyf7O7HC1Jf0VjdQ60M=
|
||||
github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||
github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4=
|
||||
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
|
||||
@ -28,22 +27,20 @@ github.com/ginuerzh/gosocks4 v0.0.1 h1:ojDKUyz+uaEeRm2usY1cyQiXTqJqrKxfeE6SVBXq4
|
||||
github.com/ginuerzh/gosocks4 v0.0.1/go.mod h1:8SdwBMKjfJ9+BfP2vDJM1jcrgWUbWV6qxBPHHVrwptY=
|
||||
github.com/ginuerzh/gosocks5 v0.2.0 h1:K0Ua23U9LU3BZrf3XpGDcs0mP8DiEpa6PJE4TA/MU3s=
|
||||
github.com/ginuerzh/gosocks5 v0.2.0/go.mod h1:qp22mr6tH/prEoaN0pFukq76LlScIE+F2rP2ZP5ZHno=
|
||||
github.com/ginuerzh/tls-dissector v0.0.1 h1:yF6fIt78TO4CdjiLLn6R8r0XajQJE1Lbnuq6rP8mGW8=
|
||||
github.com/ginuerzh/tls-dissector v0.0.1/go.mod h1:u/kbBOqIOgJv39gywuUb3VwyzdZG5DKquOqfToKE6lk=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223041816-c0cb3da7ea91 h1:bFBTbZglO4xNVWSLwDEcVKBIurTXGL2sNKi9UuQima4=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223041816-c0cb3da7ea91/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223072427-83db9c3e4eb5 h1:pmGmno31njvF5xncoDcDuM8mE1984cxrQ0DeVD4lVfA=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223072427-83db9c3e4eb5/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223110639-e9c10af0eb19 h1:t/AZCq8FiVNN+Mx6UmIv7bXj3+OVThg070G8ajZ3wJw=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223110639-e9c10af0eb19/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223121713-a8bf02a99d69 h1:h9lREy0OWSTrjweGxduikppA2tCjGPoUj32SVHI3dr0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200223121713-a8bf02a99d69/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796 h1:VPXbYRvZUzTemsI7u0FzOnEuHeHwQuMTPXApAu8aeX4=
|
||||
github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0=
|
||||
github.com/go-gost/bpool v1.0.0 h1:Og+6SH6SooHqf8CIwuxcPRHq8k0Si4YEfO2mBEi3/Uk=
|
||||
github.com/go-gost/bpool v1.0.0/go.mod h1:y/Pywm22A4OrJqNF/mL4nW7yb9fCdhlO8cxjyparkFI=
|
||||
github.com/go-gost/bypass v1.0.0 h1:ZhLzA3WY9JDxmpyuGwVUH0ubaFOmWWzNpejzwExvhMA=
|
||||
github.com/go-gost/bypass v1.0.0/go.mod h1:r2MYlxn1/fs24NFs+h/m9HiZKfckBrTnONXklxRUwcE=
|
||||
github.com/go-gost/hosts v1.0.0 h1:KnUBEuIZ6CtMAvGN0n8vYvYahPuMMAu58HGFm2QKEhE=
|
||||
github.com/go-gost/hosts v1.0.0/go.mod h1:6MrBWeZaRKo/ZwKhtSRK49C+rd3b8Hun4rhuRiYT6bI=
|
||||
github.com/go-gost/log v1.0.0 h1:maSjjMvQqLSQYb0Ta5nJTdlRI+aiLMt6WIBYVxajJgs=
|
||||
github.com/go-gost/log v1.0.0/go.mod h1:FCOaaJQ7moHTlLxYk7dsFewlS68U9A1GG3OR+yXkF6s=
|
||||
github.com/go-gost/relay v0.1.0 h1:UOf2YwAzzaUjY5mdpMuLfSw0vz62iIFYk7oJQkuhlGw=
|
||||
github.com/go-gost/relay v0.1.0/go.mod h1:YFCpddLOFE3NlIkeDWRdEs8gL/GFsqXdtaf8SV5v4YQ=
|
||||
github.com/go-log/log v0.1.0 h1:wudGTNsiGzrD5ZjgIkVZ517ugi2XRe9Q/xRCzwEO4/U=
|
||||
github.com/go-log/log v0.1.0/go.mod h1:4mBwpdRMFLiuXZDCwU2lKQFsoSCo72j3HqBK9d81N2M=
|
||||
github.com/go-gost/reloader v1.1.0 h1:ovbHzWTzmKVZdqgmuBsLIeCq6GRAMlcwargAxk4roBo=
|
||||
github.com/go-gost/reloader v1.1.0/go.mod h1:9EbWvTaddhwuIKlR3Byto/oHamAf/kIGKf333ALfpT0=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
@ -64,6 +61,8 @@ github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/reedsolomon v1.7.0 h1:pLFmRKGko2ZieiTGyo9DahLCIuljyxm+Zzhz/fYEonE=
|
||||
github.com/klauspost/reedsolomon v1.7.0/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
|
||||
github.com/libp2p/go-buffer-pool v0.0.3-0.20191206215133-4016316b51a2 h1:pSnSOZz0cmK3c6944tZdBq7Je9Qf28w80n+PCaq+2Qk=
|
||||
github.com/libp2p/go-buffer-pool v0.0.3-0.20191206215133-4016316b51a2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
||||
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f h1:sSeNEkJrs+0F9TUau0CgWTTNEwF23HST3Eq0A+QIx+A=
|
||||
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04=
|
||||
github.com/lucas-clemente/quic-go v0.10.0 h1:xEF+pSHYAOcu+U10Meunf+DTtc8vhQDRqlA0BJ6hufc=
|
||||
@ -83,8 +82,6 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.0.12-0.20191211020244-a57bc393e43a h1:cxYYZwo6iuuJ/5f8x1mHnya7xvSF3cDrOh8Pqh7RZ/w=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.0.12-0.20191211020244-a57bc393e43a/go.mod h1:/0aFGbhK8mtOX4J/6kTJsPLZlEs9KnzKoWCOCvjd7vk=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.0 h1:jQhkjAmMuOTQ7B04bnrRJ5IAoZEwoaXXkKspE7rQ6ck=
|
||||
github.com/shadowsocks/go-shadowsocks2 v0.1.0/go.mod h1:/0aFGbhK8mtOX4J/6kTJsPLZlEs9KnzKoWCOCvjd7vk=
|
||||
github.com/shadowsocks/shadowsocks-go v0.0.0-20170121203516-97a5c71f80ba h1:tJgNXb3S+RkB4kNPi6N5OmEWe3m+Y3Qs6LUMiNDAONM=
|
||||
@ -100,17 +97,14 @@ github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/
|
||||
github.com/xtaci/tcpraw v1.2.25 h1:VDlqo0op17JeXBM6e2G9ocCNLOJcw9mZbobMbJjo0vk=
|
||||
github.com/xtaci/tcpraw v1.2.25/go.mod h1:dKyZ2V75s0cZ7cbgJYdxPvms7af0joIeOyx1GgJQbLk=
|
||||
golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
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-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
|
||||
@ -120,7 +114,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
|
||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPTs2tR8uOySCbBP7BN/M=
|
||||
|
21
gost.go
21
gost.go
@ -13,10 +13,9 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
// Version is the gost version.
|
||||
@ -32,24 +31,6 @@ var (
|
||||
largeBufferSize = 32 * 1024 // 32KB large buffer
|
||||
)
|
||||
|
||||
var (
|
||||
sPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, smallBufferSize)
|
||||
},
|
||||
}
|
||||
mPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, mediumBufferSize)
|
||||
},
|
||||
}
|
||||
lPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, largeBufferSize)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
// KeepAliveTime is the keep alive time period for TCP connection.
|
||||
KeepAliveTime = 180 * time.Second
|
||||
|
14
handler.go
14
handler.go
@ -9,7 +9,9 @@ import (
|
||||
|
||||
"github.com/ginuerzh/gosocks4"
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bypass"
|
||||
"github.com/go-gost/hosts"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
// Handler is a proxy server handler
|
||||
@ -30,11 +32,11 @@ type HandlerOptions struct {
|
||||
Strategy Strategy
|
||||
MaxFails int
|
||||
FailTimeout time.Duration
|
||||
Bypass *Bypass
|
||||
Bypasser bypass.Bypasser
|
||||
Retries int
|
||||
Timeout time.Duration
|
||||
Resolver Resolver
|
||||
Hosts *Hosts
|
||||
Hosts hosts.Hosts
|
||||
ProbeResist string
|
||||
KnockingHost string
|
||||
Node Node
|
||||
@ -107,9 +109,9 @@ func BlacklistHandlerOption(blacklist *Permissions) HandlerOption {
|
||||
}
|
||||
|
||||
// BypassHandlerOption sets the bypass option of HandlerOptions.
|
||||
func BypassHandlerOption(bypass *Bypass) HandlerOption {
|
||||
func BypasserHandlerOption(bypasser bypass.Bypasser) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.Bypass = bypass
|
||||
opts.Bypasser = bypasser
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +158,7 @@ func ResolverHandlerOption(resolver Resolver) HandlerOption {
|
||||
}
|
||||
|
||||
// HostsHandlerOption sets the Hosts option of HandlerOptions.
|
||||
func HostsHandlerOption(hosts *Hosts) HandlerOption {
|
||||
func HostsHandlerOption(hosts hosts.Hosts) HandlerOption {
|
||||
return func(opts *HandlerOptions) {
|
||||
opts.Hosts = hosts
|
||||
}
|
||||
|
160
hosts.go
160
hosts.go
@ -1,160 +0,0 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
)
|
||||
|
||||
// Host is a static mapping from hostname to 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
|
||||
period time.Duration
|
||||
stopped chan struct{}
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
// NewHosts creates a Hosts with optional list of hosts.
|
||||
func NewHosts(hosts ...Host) *Hosts {
|
||||
return &Hosts{
|
||||
hosts: hosts,
|
||||
stopped: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// AddHost adds host(s) to the host table.
|
||||
func (h *Hosts) AddHost(host ...Host) {
|
||||
h.mux.Lock()
|
||||
defer h.mux.Unlock()
|
||||
|
||||
h.hosts = append(h.hosts, host...)
|
||||
}
|
||||
|
||||
// Lookup searches the IP address corresponds to the given host from the host table.
|
||||
func (h *Hosts) Lookup(host string) (ip net.IP) {
|
||||
if h == nil || host == "" {
|
||||
return
|
||||
}
|
||||
|
||||
h.mux.RLock()
|
||||
defer h.mux.RUnlock()
|
||||
|
||||
for _, h := range h.hosts {
|
||||
if h.Hostname == host {
|
||||
ip = h.IP
|
||||
break
|
||||
}
|
||||
for _, alias := range h.Aliases {
|
||||
if alias == host {
|
||||
ip = h.IP
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if ip != nil && Debug {
|
||||
log.Logf("[hosts] hit: %s %s", host, ip.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Reload parses config from r, then live reloads the hosts.
|
||||
func (h *Hosts) Reload(r io.Reader) error {
|
||||
var period time.Duration
|
||||
var hosts []Host
|
||||
|
||||
if r == nil || h.Stopped() {
|
||||
return nil
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
ss := splitLine(line)
|
||||
if len(ss) < 2 {
|
||||
continue // invalid lines are ignored
|
||||
}
|
||||
|
||||
switch ss[0] {
|
||||
case "reload": // reload option
|
||||
period, _ = time.ParseDuration(ss[1])
|
||||
default:
|
||||
ip := net.ParseIP(ss[0])
|
||||
if ip == nil {
|
||||
break // invalid IP addresses are ignored
|
||||
}
|
||||
host := Host{
|
||||
IP: ip,
|
||||
Hostname: ss[1],
|
||||
}
|
||||
if len(ss) > 2 {
|
||||
host.Aliases = ss[2:]
|
||||
}
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.mux.Lock()
|
||||
h.period = period
|
||||
h.hosts = hosts
|
||||
h.mux.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Period returns the reload period
|
||||
func (h *Hosts) Period() time.Duration {
|
||||
if h.Stopped() {
|
||||
return -1
|
||||
}
|
||||
|
||||
h.mux.RLock()
|
||||
defer h.mux.RUnlock()
|
||||
|
||||
return h.period
|
||||
}
|
||||
|
||||
// Stop stops reloading.
|
||||
func (h *Hosts) Stop() {
|
||||
select {
|
||||
case <-h.stopped:
|
||||
default:
|
||||
close(h.stopped)
|
||||
}
|
||||
}
|
||||
|
||||
// Stopped checks whether the reloader is stopped.
|
||||
func (h *Hosts) Stopped() bool {
|
||||
select {
|
||||
case <-h.stopped:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
130
hosts_test.go
130
hosts_test.go
@ -1,130 +0,0 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var hostsLookupTests = []struct {
|
||||
hosts []Host
|
||||
host string
|
||||
ip net.IP
|
||||
}{
|
||||
{nil, "", nil},
|
||||
{nil, "example.com", nil},
|
||||
{[]Host{}, "", nil},
|
||||
{[]Host{}, "example.com", nil},
|
||||
{[]Host{NewHost(nil, "")}, "", nil},
|
||||
{[]Host{NewHost(nil, "example.com")}, "example.com", nil},
|
||||
{[]Host{NewHost(net.IPv4(192, 168, 1, 1), "")}, "", nil},
|
||||
{[]Host{NewHost(net.IPv4(192, 168, 1, 1), "example.com")}, "example.com", net.IPv4(192, 168, 1, 1)},
|
||||
{[]Host{NewHost(net.IPv4(192, 168, 1, 1), "example.com")}, "example", nil},
|
||||
{[]Host{NewHost(net.IPv4(192, 168, 1, 1), "example.com", "example", "examples")}, "example", net.IPv4(192, 168, 1, 1)},
|
||||
{[]Host{NewHost(net.IPv4(192, 168, 1, 1), "example.com", "example", "examples")}, "examples", net.IPv4(192, 168, 1, 1)},
|
||||
}
|
||||
|
||||
func TestHostsLookup(t *testing.T) {
|
||||
for i, tc := range hostsLookupTests {
|
||||
hosts := NewHosts()
|
||||
hosts.AddHost(tc.hosts...)
|
||||
ip := hosts.Lookup(tc.host)
|
||||
if !ip.Equal(tc.ip) {
|
||||
t.Errorf("#%d test failed: lookup should be %s, got %s", i, tc.ip, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var HostsReloadTests = []struct {
|
||||
r io.Reader
|
||||
period time.Duration
|
||||
host string
|
||||
ip net.IP
|
||||
stopped bool
|
||||
}{
|
||||
{
|
||||
r: nil,
|
||||
period: 0,
|
||||
host: "",
|
||||
ip: nil,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString(""),
|
||||
period: 0,
|
||||
host: "example.com",
|
||||
ip: nil,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("reload 10s"),
|
||||
period: 10 * time.Second,
|
||||
host: "example.com",
|
||||
ip: nil,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reload 10s\ninvalid.ip.addr example.com"),
|
||||
period: 0,
|
||||
ip: nil,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("reload 10s\n192.168.1.1"),
|
||||
period: 10 * time.Second,
|
||||
host: "",
|
||||
ip: nil,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reload 10s\n192.168.1.1 example.com"),
|
||||
period: 0,
|
||||
host: "example.com",
|
||||
ip: net.IPv4(192, 168, 1, 1),
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reload 10s\n#192.168.1.1 example.com"),
|
||||
period: 0,
|
||||
host: "example.com",
|
||||
ip: nil,
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reload 10s\n192.168.1.1 example.com example examples"),
|
||||
period: 0,
|
||||
host: "example",
|
||||
ip: net.IPv4(192, 168, 1, 1),
|
||||
stopped: true,
|
||||
},
|
||||
{
|
||||
r: bytes.NewBufferString("#reload 10s\n192.168.1.1 example.com example examples"),
|
||||
period: 0,
|
||||
host: "examples",
|
||||
ip: net.IPv4(192, 168, 1, 1),
|
||||
stopped: true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestHostsReload(t *testing.T) {
|
||||
for i, tc := range HostsReloadTests {
|
||||
hosts := NewHosts()
|
||||
if err := hosts.Reload(tc.r); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if hosts.Period() != tc.period {
|
||||
t.Errorf("#%d test failed: period value should be %v, got %v",
|
||||
i, tc.period, hosts.Period())
|
||||
}
|
||||
ip := hosts.Lookup(tc.host)
|
||||
if !ip.Equal(tc.ip) {
|
||||
t.Errorf("#%d test failed: lookup should be %s, got %s", i, tc.ip, ip)
|
||||
}
|
||||
if tc.stopped {
|
||||
hosts.Stop()
|
||||
if hosts.Period() >= 0 {
|
||||
t.Errorf("period of the stopped reloader should be minus value")
|
||||
}
|
||||
}
|
||||
if hosts.Stopped() != tc.stopped {
|
||||
t.Errorf("#%d test failed: stopped value should be %v, got %v",
|
||||
i, tc.stopped, hosts.Stopped())
|
||||
}
|
||||
}
|
||||
}
|
4
http.go
4
http.go
@ -15,7 +15,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
type httpConnector struct {
|
||||
@ -189,7 +189,7 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.options.Bypass.Contains(host) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(host) {
|
||||
resp.StatusCode = http.StatusForbidden
|
||||
|
||||
log.Logf("[http] %s - %s bypass %s",
|
||||
|
10
http2.go
10
http2.go
@ -20,7 +20,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
@ -234,7 +234,7 @@ func (tr *h2Transporter) Dial(addr string, options ...DialOption) (net.Conn, err
|
||||
|
||||
transport := http2.Transport{
|
||||
TLSClientConfig: tr.tlsConfig,
|
||||
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||
DialTLS: func(network, adr string, cfg *tls.Config) (net.Conn, error) {
|
||||
conn, err := opts.Chain.Dial(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -256,13 +256,13 @@ func (tr *h2Transporter) Dial(addr string, options ...DialOption) (net.Conn, err
|
||||
pr, pw := io.Pipe()
|
||||
req := &http.Request{
|
||||
Method: http.MethodConnect,
|
||||
URL: &url.URL{Scheme: "https", Host: addr},
|
||||
URL: &url.URL{Scheme: "https", Host: opts.Host},
|
||||
Header: make(http.Header),
|
||||
Proto: "HTTP/2.0",
|
||||
ProtoMajor: 2,
|
||||
ProtoMinor: 0,
|
||||
Body: pr,
|
||||
Host: addr,
|
||||
Host: opts.Host,
|
||||
ContentLength: -1,
|
||||
}
|
||||
if tr.path != "" {
|
||||
@ -374,7 +374,7 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.options.Bypass.Contains(host) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(host) {
|
||||
log.Logf("[http2] %s - %s bypass %s",
|
||||
r.RemoteAddr, laddr, host)
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
|
2
kcp.go
2
kcp.go
@ -13,7 +13,7 @@ import (
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/klauspost/compress/snappy"
|
||||
"github.com/xtaci/tcpraw"
|
||||
"gopkg.in/xtaci/kcp-go.v4"
|
||||
|
36
log.go
36
log.go
@ -1,36 +0,0 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
}
|
||||
|
||||
// LogLogger uses the standard log package as the logger
|
||||
type LogLogger struct {
|
||||
}
|
||||
|
||||
// Log uses the standard log library log.Output
|
||||
func (l *LogLogger) Log(v ...interface{}) {
|
||||
log.Output(3, fmt.Sprintln(v...))
|
||||
}
|
||||
|
||||
// Logf uses the standard log library log.Output
|
||||
func (l *LogLogger) Logf(format string, v ...interface{}) {
|
||||
log.Output(3, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// NopLogger is a dummy logger that discards the log outputs
|
||||
type NopLogger struct {
|
||||
}
|
||||
|
||||
// Log does nothing
|
||||
func (l *NopLogger) Log(v ...interface{}) {
|
||||
}
|
||||
|
||||
// Logf does nothing
|
||||
func (l *NopLogger) Logf(format string, v ...interface{}) {
|
||||
}
|
4
node.go
4
node.go
@ -8,6 +8,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-gost/bypass"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -31,7 +33,7 @@ type Node struct {
|
||||
ConnectOptions []ConnectOption
|
||||
Client *Client
|
||||
marker *failMarker
|
||||
Bypass *Bypass
|
||||
Bypasser bypass.Bypasser
|
||||
}
|
||||
|
||||
// ParseNode parses the node info.
|
||||
|
2
obfs.go
2
obfs.go
@ -17,7 +17,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
|
||||
pt "git.torproject.org/pluggable-transports/goptlib.git"
|
||||
"git.torproject.org/pluggable-transports/obfs4.git/transports/base"
|
||||
|
2
quic.go
2
quic.go
@ -11,7 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
quic "github.com/lucas-clemente/quic-go"
|
||||
)
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/LiamHaworth/go-tproxy"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
type tcpRedirectHandler struct {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
type tcpRedirectHandler struct {
|
||||
|
7
relay.go
7
relay.go
@ -13,8 +13,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/go-gost/relay"
|
||||
"github.com/go-log/log"
|
||||
)
|
||||
|
||||
type relayConnector struct {
|
||||
@ -338,8 +339,8 @@ func (c *relayConn) Write(b []byte) (n int, err error) {
|
||||
nsize := 2 + len(b)
|
||||
var buf []byte
|
||||
if nsize <= mediumBufferSize {
|
||||
buf = mPool.Get().([]byte)
|
||||
defer mPool.Put(buf)
|
||||
buf = bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(buf)
|
||||
} else {
|
||||
buf = make([]byte, nsize)
|
||||
}
|
||||
|
65
reload.go
65
reload.go
@ -1,65 +0,0 @@
|
||||
package gost
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
)
|
||||
|
||||
// Reloader is the interface for objects that support live reloading.
|
||||
type Reloader interface {
|
||||
Reload(r io.Reader) error
|
||||
Period() time.Duration
|
||||
}
|
||||
|
||||
// Stoppable is the interface that indicates a Reloader can be stopped.
|
||||
type Stoppable interface {
|
||||
Stop()
|
||||
Stopped() bool
|
||||
}
|
||||
|
||||
// PeriodReload reloads the config configFile periodically according to the period of the Reloader r.
|
||||
func PeriodReload(r Reloader, configFile string) error {
|
||||
if r == nil || configFile == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var lastMod time.Time
|
||||
for {
|
||||
if r.Period() < 0 {
|
||||
log.Log("[reload] stopped:", configFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.Open(configFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mt := lastMod
|
||||
if finfo, err := f.Stat(); err == nil {
|
||||
mt = finfo.ModTime()
|
||||
}
|
||||
|
||||
if !lastMod.IsZero() && !mt.Equal(lastMod) {
|
||||
log.Log("[reload]", configFile)
|
||||
if err := r.Reload(f); err != nil {
|
||||
log.Logf("[reload] %s: %s", configFile, err)
|
||||
}
|
||||
}
|
||||
f.Close()
|
||||
lastMod = mt
|
||||
|
||||
period := r.Period()
|
||||
if period == 0 {
|
||||
log.Log("[reload] disabled:", configFile)
|
||||
return nil
|
||||
}
|
||||
if period < time.Second {
|
||||
period = time.Second
|
||||
}
|
||||
<-time.After(period)
|
||||
}
|
||||
}
|
@ -16,7 +16,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/go-gost/reloader"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
@ -180,8 +181,8 @@ type Resolver interface {
|
||||
// ReloadResolver is resolover that support live reloading.
|
||||
type ReloadResolver interface {
|
||||
Resolver
|
||||
Reloader
|
||||
Stoppable
|
||||
reloader.Reloader
|
||||
reloader.Stoppable
|
||||
}
|
||||
|
||||
type resolver struct {
|
||||
|
@ -5,7 +5,8 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
// Accepter represents a network endpoint that can accept connection from peer.
|
||||
@ -120,8 +121,8 @@ func transport(rw1, rw2 io.ReadWriter) error {
|
||||
}
|
||||
|
||||
func copyBuffer(dst io.Writer, src io.Reader) error {
|
||||
buf := lPool.Get().([]byte)
|
||||
defer lPool.Put(buf)
|
||||
buf := bpool.Get(largeBufferSize)
|
||||
defer bpool.Put(buf)
|
||||
|
||||
_, err := io.CopyBuffer(dst, src, buf)
|
||||
return err
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"gopkg.in/xtaci/kcp-go.v4"
|
||||
)
|
||||
|
||||
|
4
sni.go
4
sni.go
@ -18,7 +18,7 @@ import (
|
||||
"sync"
|
||||
|
||||
dissector "github.com/ginuerzh/tls-dissector"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
type sniConnector struct {
|
||||
@ -113,7 +113,7 @@ func (h *sniHandler) Handle(conn net.Conn) {
|
||||
conn.RemoteAddr(), conn.LocalAddr(), host)
|
||||
return
|
||||
}
|
||||
if h.options.Bypass.Contains(host) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(host) {
|
||||
log.Log("[sni] %s - %s bypass %s",
|
||||
conn.RemoteAddr(), conn.LocalAddr(), host)
|
||||
return
|
||||
|
39
socks.go
39
socks.go
@ -15,7 +15,8 @@ import (
|
||||
|
||||
"github.com/ginuerzh/gosocks4"
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
smux "gopkg.in/xtaci/smux.v1"
|
||||
)
|
||||
|
||||
@ -899,7 +900,7 @@ func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if h.options.Bypass.Contains(host) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(host) {
|
||||
log.Logf("[socks5] %s - %s : Bypass %s",
|
||||
conn.RemoteAddr(), conn.LocalAddr(), host)
|
||||
rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
|
||||
@ -1238,8 +1239,8 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) {
|
||||
var clientAddr net.Addr
|
||||
|
||||
go func() {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
for {
|
||||
n, laddr, err := relay.ReadFrom(b)
|
||||
@ -1260,7 +1261,7 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) {
|
||||
if err != nil {
|
||||
continue // drop silently
|
||||
}
|
||||
if h.options.Bypass.Contains(raddr.String()) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(raddr.String()) {
|
||||
log.Log("[socks5-udp] [bypass] write to", raddr)
|
||||
continue // bypass
|
||||
}
|
||||
@ -1275,8 +1276,8 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) {
|
||||
}()
|
||||
|
||||
go func() {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
for {
|
||||
n, raddr, err := peer.ReadFrom(b)
|
||||
@ -1287,7 +1288,7 @@ func (h *socks5Handler) transportUDP(relay, peer net.PacketConn) (err error) {
|
||||
if clientAddr == nil {
|
||||
continue
|
||||
}
|
||||
if h.options.Bypass.Contains(raddr.String()) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(raddr.String()) {
|
||||
log.Log("[socks5-udp] [bypass] read from", raddr)
|
||||
continue // bypass
|
||||
}
|
||||
@ -1318,8 +1319,8 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error
|
||||
var clientAddr *net.UDPAddr
|
||||
|
||||
go func() {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
for {
|
||||
n, addr, err := uc.ReadFromUDP(b)
|
||||
@ -1340,7 +1341,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error
|
||||
clientAddr = addr
|
||||
}
|
||||
raddr := dgram.Header.Addr.String()
|
||||
if h.options.Bypass.Contains(raddr) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(raddr) {
|
||||
log.Log("[udp-tun] [bypass] write to", raddr)
|
||||
continue // bypass
|
||||
}
|
||||
@ -1369,7 +1370,7 @@ func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error
|
||||
continue
|
||||
}
|
||||
raddr := dgram.Header.Addr.String()
|
||||
if h.options.Bypass.Contains(raddr) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(raddr) {
|
||||
log.Log("[udp-tun] [bypass] read from", raddr)
|
||||
continue // bypass
|
||||
}
|
||||
@ -1458,8 +1459,8 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err
|
||||
errc := make(chan error, 2)
|
||||
|
||||
go func() {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
for {
|
||||
n, addr, err := pc.ReadFrom(b)
|
||||
@ -1468,7 +1469,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
if h.options.Bypass.Contains(addr.String()) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(addr.String()) {
|
||||
log.Log("[socks5] udp-tun bypass read from", addr)
|
||||
continue // bypass
|
||||
}
|
||||
@ -1501,7 +1502,7 @@ func (h *socks5Handler) tunnelServerUDP(cc net.Conn, pc net.PacketConn) (err err
|
||||
if err != nil {
|
||||
continue // drop silently
|
||||
}
|
||||
if h.options.Bypass.Contains(addr.String()) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(addr.String()) {
|
||||
log.Log("[socks5] udp-tun bypass write to", addr)
|
||||
continue // bypass
|
||||
}
|
||||
@ -1714,7 +1715,7 @@ func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if h.options.Bypass.Contains(addr) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(addr) {
|
||||
log.Log("[socks4] %s - %s : Bypass %s",
|
||||
conn.RemoteAddr(), conn.LocalAddr(), addr)
|
||||
rep := gosocks4.NewReply(gosocks4.Rejected, nil)
|
||||
@ -2033,8 +2034,8 @@ func (c *socks5UDPConn) Read(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (c *socks5UDPConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||
data := mPool.Get().([]byte)
|
||||
defer mPool.Put(data)
|
||||
data := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(data)
|
||||
|
||||
n, err = c.UDPConn.Read(data)
|
||||
if err != nil {
|
||||
|
37
ss.go
37
ss.go
@ -11,7 +11,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ginuerzh/gosocks5"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||
ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
|
||||
)
|
||||
@ -61,8 +62,8 @@ func (c *shadowConnector) ConnectContext(ctx context.Context, conn net.Conn, net
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawaddr := sPool.Get().([]byte)
|
||||
defer sPool.Put(rawaddr)
|
||||
rawaddr := bpool.Get(smallBufferSize)
|
||||
defer bpool.Put(rawaddr)
|
||||
|
||||
n, err := socksAddr.Encode(rawaddr)
|
||||
if err != nil {
|
||||
@ -148,7 +149,7 @@ func (h *shadowHandler) Handle(conn net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.options.Bypass.Contains(host) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(host) {
|
||||
log.Logf("[ss] %s - %s : Bypass %s",
|
||||
conn.RemoteAddr(), conn.LocalAddr(), host)
|
||||
return
|
||||
@ -340,8 +341,8 @@ func (h *shadowUDPHandler) transportPacket(conn, cc net.PacketConn) (err error)
|
||||
go func() {
|
||||
for {
|
||||
err := func() error {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, addr, err := conn.ReadFrom(b)
|
||||
if err != nil {
|
||||
@ -377,8 +378,8 @@ func (h *shadowUDPHandler) transportPacket(conn, cc net.PacketConn) (err error)
|
||||
go func() {
|
||||
for {
|
||||
err := func() error {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, addr, err := cc.ReadFrom(b)
|
||||
if err != nil {
|
||||
@ -434,7 +435,7 @@ func (h *shadowUDPHandler) transportUDP(conn net.Conn, cc net.PacketConn) error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if h.options.Bypass.Contains(addr.String()) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(addr.String()) {
|
||||
log.Log("[ssu] bypass", addr)
|
||||
return // bypass
|
||||
}
|
||||
@ -452,8 +453,8 @@ func (h *shadowUDPHandler) transportUDP(conn net.Conn, cc net.PacketConn) error
|
||||
go func() {
|
||||
for {
|
||||
er := func() (err error) {
|
||||
b := mPool.Get().([]byte)
|
||||
defer mPool.Put(b)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, addr, err := cc.ReadFrom(b)
|
||||
if err != nil {
|
||||
@ -462,7 +463,7 @@ func (h *shadowUDPHandler) transportUDP(conn net.Conn, cc net.PacketConn) error
|
||||
if Debug {
|
||||
log.Logf("[ssu] %s <<< %s length: %d", conn.RemoteAddr(), addr, n)
|
||||
}
|
||||
if h.options.Bypass.Contains(addr.String()) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(addr.String()) {
|
||||
log.Log("[ssu] bypass", addr)
|
||||
return // bypass
|
||||
}
|
||||
@ -514,8 +515,8 @@ type shadowUDPPacketConn struct {
|
||||
}
|
||||
|
||||
func (c *shadowUDPPacketConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||
buf := mPool.Get().([]byte)
|
||||
defer mPool.Put(buf)
|
||||
buf := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(buf)
|
||||
|
||||
buf[0] = 0
|
||||
buf[1] = 0
|
||||
@ -553,8 +554,8 @@ func (c *shadowUDPPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error
|
||||
return
|
||||
}
|
||||
|
||||
buf := mPool.Get().([]byte)
|
||||
defer mPool.Put(buf)
|
||||
buf := bpool.Get(mediumBufferSize)
|
||||
defer bpool.Put(buf)
|
||||
|
||||
copy(buf, rawaddr[:nn])
|
||||
n = copy(buf[nn:], b)
|
||||
@ -611,8 +612,8 @@ func initShadowCipher(info *url.Userinfo) (cipher core.Cipher) {
|
||||
|
||||
func readSocksAddr(r io.Reader) (*gosocks5.Addr, error) {
|
||||
addr := &gosocks5.Addr{}
|
||||
b := sPool.Get().([]byte)
|
||||
defer sPool.Put(b)
|
||||
b := bpool.Get(smallBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
_, err := io.ReadFull(r, b[:1])
|
||||
if err != nil {
|
||||
|
4
ssh.go
4
ssh.go
@ -13,7 +13,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
@ -608,7 +608,7 @@ func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr
|
||||
return
|
||||
}
|
||||
|
||||
if h.options.Bypass.Contains(raddr) {
|
||||
if h.options.Bypasser != nil && h.options.Bypasser.Bypass(raddr) {
|
||||
log.Logf("[ssh-tcp] [bypass] %s", raddr)
|
||||
return
|
||||
}
|
||||
|
2
tls.go
2
tls.go
@ -8,7 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
|
||||
smux "gopkg.in/xtaci/smux.v1"
|
||||
)
|
||||
|
24
tuntap.go
24
tuntap.go
@ -10,10 +10,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/shadowsocks/go-shadowsocks2/core"
|
||||
"github.com/shadowsocks/go-shadowsocks2/shadowaead"
|
||||
"github.com/shadowsocks/go-shadowsocks2/shadowstream"
|
||||
"github.com/songgao/water"
|
||||
"github.com/songgao/water/waterutil"
|
||||
"github.com/xtaci/tcpraw"
|
||||
@ -261,8 +261,8 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
||||
go func() {
|
||||
for {
|
||||
err := func() error {
|
||||
b := sPool.Get().([]byte)
|
||||
defer sPool.Put(b)
|
||||
b := bpool.Get(smallBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, err := tun.Read(b)
|
||||
if err != nil {
|
||||
@ -335,12 +335,12 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
||||
go func() {
|
||||
for {
|
||||
err := func() error {
|
||||
b := sPool.Get().([]byte)
|
||||
defer sPool.Put(b)
|
||||
b := bpool.Get(smallBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, addr, err := conn.ReadFrom(b)
|
||||
if err != nil &&
|
||||
err != shadowaead.ErrShortPacket && err != shadowstream.ErrShortPacket {
|
||||
err != shadowaead.ErrShortPacket {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -637,8 +637,8 @@ func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.A
|
||||
go func() {
|
||||
for {
|
||||
err := func() error {
|
||||
b := sPool.Get().([]byte)
|
||||
defer sPool.Put(b)
|
||||
b := bpool.Get(smallBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, err := tap.Read(b)
|
||||
if err != nil {
|
||||
@ -697,12 +697,12 @@ func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.A
|
||||
go func() {
|
||||
for {
|
||||
err := func() error {
|
||||
b := sPool.Get().([]byte)
|
||||
defer sPool.Put(b)
|
||||
b := bpool.Get(smallBufferSize)
|
||||
defer bpool.Put(b)
|
||||
|
||||
n, addr, err := conn.ReadFrom(b)
|
||||
if err != nil &&
|
||||
err != shadowaead.ErrShortPacket && err != shadowstream.ErrShortPacket {
|
||||
err != shadowaead.ErrShortPacket {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/songgao/water"
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/libcontainer/netlink"
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/milosgajdos83/tenus"
|
||||
"github.com/songgao/water"
|
||||
)
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/songgao/water"
|
||||
)
|
||||
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/log"
|
||||
"github.com/songgao/water"
|
||||
)
|
||||
|
||||
|
7
udp.go
7
udp.go
@ -7,7 +7,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-log/log"
|
||||
"github.com/go-gost/bpool"
|
||||
"github.com/go-gost/log"
|
||||
)
|
||||
|
||||
// udpTransporter is a raw UDP transporter.
|
||||
@ -90,7 +91,7 @@ func UDPListener(addr string, cfg *UDPListenConfig) (Listener, error) {
|
||||
func (l *udpListener) listenLoop() {
|
||||
for {
|
||||
// NOTE: this buffer will be released in the udpServerConn after read.
|
||||
b := mPool.Get().([]byte)
|
||||
b := bpool.Get(mediumBufferSize)
|
||||
|
||||
n, raddr, err := l.ln.ReadFrom(b)
|
||||
if err != nil {
|
||||
@ -243,7 +244,7 @@ func (c *udpServerConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
|
||||
case bb := <-c.rChan:
|
||||
n = copy(b, bb)
|
||||
if cap(bb) == mediumBufferSize {
|
||||
mPool.Put(bb[:cap(bb)])
|
||||
bpool.Put(bb[:cap(bb)])
|
||||
}
|
||||
case <-c.closed:
|
||||
err = errors.New("read from closed connection")
|
||||
|
Loading…
Reference in New Issue
Block a user