Compare commits

...
30 Commits
Author SHA1 Message Date
wweir 9a158d4088 Optimize QUIC paramaters 2019-03-02 09:22:31 +08:00
wweir 88990cddd9 Update dependency 2019-03-02 09:07:20 +08:00
wweir ca1b2650ab Optimize install script 2019-03-02 08:07:01 +08:00
wweir 8ff1046ebf Merge branch 'bug/suffix-tree' 2019-02-28 17:38:52 +08:00
wweir dfe81f6f23 Fix suffix tree match logic 2019-02-28 17:38:34 +08:00
wweir 972875ec36 Optimize default rules 2019-02-28 16:14:40 +08:00
wweir 89b7a41d46 Add rule for mail 2019-02-28 15:40:57 +08:00
wweir 8f598dbc17 Optimize ci workflow 2019-02-27 14:28:54 +08:00
wweir 192b4f798b Optimize suggest logic 2019-02-27 14:16:02 +08:00
wweir 2adefe0dfc Fix clear dns command for windows 2019-02-26 17:33:39 +08:00
wweir 7b0c13ef1c Merge branch 'refactor/watch-config' 2019-02-24 18:20:31 +08:00
wweir 63bb934148 Release config file immediatly 2019-02-24 18:18:43 +08:00
wweir cacc732a4e Remove fsnotify, add refresh trigger for config 2019-02-24 17:43:17 +08:00
wweir 17d079dcb2 Fix #3, Merge branch 'feature/windows_svc' 2019-02-24 16:12:05 +08:00
wweir 413a93f6f7 Support Windows service deploy 2019-02-24 16:10:19 +08:00
wweir 6c5f5cd74f Add windows service support 2019-02-24 15:58:38 +08:00
wweir e948541efe Merge branch 'chore/code' 2019-02-19 16:53:21 +08:00
wweir ffa2128274 Move code files path 2019-02-19 16:53:08 +08:00
wweir b53b7874b6 Update README.md 2019-02-19 16:24:47 +08:00
wweir f3117edfa0 For macOS without brew 2019-02-19 13:04:36 +08:00
wweir ba8980da73 Limit dns detect timeout short than 1s for multi dns setting 2019-02-17 07:29:23 +08:00
wweir e3ec74b74f Merge branch 'bug/resolve-addr' 2019-02-16 22:41:28 +08:00
wweir 6e67193894 Release on tag 2019-02-16 22:40:54 +08:00
wweir af0c5f895c Fix resolve for dhcp 2019-02-16 22:26:20 +08:00
wweir 4883e240cc Merge branch 'feature/score' @release 2019-02-15 22:48:06 +08:00
wweir 18ee9ca993 Refactor intelligent detect to score logic 2019-02-15 22:47:51 +08:00
wweir 4fff2a1f3b Merge branch 'bug/dhcp-linux' @release 2019-02-15 00:28:53 +08:00
wweir 3e82890c33 Fix dhcp conflict with dhcpcd and dhclient 2019-02-15 00:27:03 +08:00
wweir 01d66d737b Merge branch 'bug/suggest' @release 2019-02-13 21:08:00 +08:00
wweir e342dadaf1 Fix http ping logic for suggestions 2019-02-13 21:07:40 +08:00
22 changed files with 479 additions and 228 deletions
+27 -21
View File
@@ -2,10 +2,9 @@ version: 2
jobs:
build:
docker:
- image: circleci/golang:1.11.4
- image: circleci/golang:1.12
steps:
- checkout # check out the code in the project directory
- setup_remote_docker # install docker in docker
- run:
name: Prepare Environment
command: |
@@ -13,39 +12,46 @@ jobs:
cp deploy/* .
mkdir artifacts
- run:
name: build linux Binary
name: Run Unit Test
command: |
make test
- run:
name: Build linux Binary
command: |
make build
tar czvf artifacts/sower_linux_amd64.tar.gz sower sower.toml sower-client.service sower-server.service
- run:
name: build macOS Binary
name: Build macOS Binary
command: |
GOOS=darwin GOARCH=amd64 make build
tar czvf artifacts/sower_darwin_amd64.tar.gz sower sower.toml cc.wweir.sower.plist
- run:
name: build Windows Binary
name: Build Windows Binary
command: |
GOOS=windows GOARCH=amd64 make build
tar czvf artifacts/sower_windows_amd64.tar.gz sower sower.toml
- run:
name: Publish Release on GitHub
command: |
if git log -1 --pretty='%s' | grep -oE '(^|\s)@release(\s|$)'; then
GHR_VERSION="$(curl -s "https://api.github.com/repos/tcnksm/ghr/releases/latest" | awk -F '"' '/tag_name/{printf $4}')"
curl -SLf https://github.com/tcnksm/ghr/releases/download/"$GHR_VERSION"/ghr_"$GHR_VERSION"_linux_amd64.tar.gz | tar xzC /go/bin --strip-components=1
git describe --tags | grep - && exit
VERSION=$(git describe --tags)
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION%-*-*} artifacts/
fi
GHR_VERSION="$(curl -s "https://api.github.com/repos/tcnksm/ghr/releases/latest" | awk -F '"' '/tag_name/{printf $4}')"
curl -SLf https://github.com/tcnksm/ghr/releases/download/"$GHR_VERSION"/ghr_"$GHR_VERSION"_linux_amd64.tar.gz | tar xzC /go/bin --strip-components=1
VERSION=$(git describe --tags)
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${VERSION%-*-*} artifacts/
- setup_remote_docker # install docker in docker
- run:
name: build docker image
name: Build Docker Image
command: |
if git log -1 --pretty='%s' | grep -oE '(^|\s)@release(\s|$)'; then
docker login -u $DOCKER_USER -p $DOCKER_PASS
make image
VERSION=$(git describe --tags)
docker tag sower wweir/sower:${VERSION%-*-*}
docker push wweir/sower:${VERSION%-*-*}
docker tag sower wweir/sower:latest
docker push wweir/sower:latest
fi
git describe --tags | grep - && exit
docker login -u $DOCKER_USER -p $DOCKER_PASS
make image
VERSION=$(git describe --tags)
docker tag sower wweir/sower:${VERSION%-*-*}
docker push wweir/sower:${VERSION%-*-*}
docker tag sower wweir/sower:latest
docker push wweir/sower:latest
+1
View File
@@ -18,4 +18,5 @@
.vscode
.idea
sower
sower.exe*
/sower.toml
+1
View File
@@ -5,6 +5,7 @@ default: test build
generate:
go generate ./...
test:
go vet ./...
go test -race ./...
build:
GO111MODULE=on go build -v -ldflags \
+2
View File
@@ -5,6 +5,8 @@
[![GitHub star](https://img.shields.io/github/stars/wweir/sower.svg?style=popout)](https://github.com/wweir/sower/stargazers)
[![GitHub license](https://img.shields.io/github/license/wweir/sower.svg?style=popout)](LICENSE)
中文介绍见 [Wiki](https://github.com/wweir/sower/wiki)
The sower is a cross-platform intelligent transparent proxy tool base on DNS solution.
The first time you visit a new website, sower will detect if the domain in block list and add it in suggect list. So that, you do not need to care about the rules, sower will handle it in a intelligent way.
+38 -67
View File
@@ -5,17 +5,17 @@ import (
"flag"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"sync"
"time"
"github.com/golang/glog"
toml "github.com/pelletier/go-toml"
"github.com/wweir/fsnotify"
"github.com/wweir/sower/util"
)
// Conf define the config items
var Conf = struct {
ConfigFile string
NetType string `toml:"net_type"`
@@ -35,19 +35,17 @@ var Conf = struct {
Suggestions []string `toml:"suggestions"`
Verbose int `toml:"verbose"`
}{}
var mu = &sync.Mutex{}
// OnRefreash will be executed while init and write new config
var OnRefreash = []func() error{
func() (err error) {
mu.Lock()
defer mu.Unlock()
f, err := os.OpenFile(Conf.ConfigFile, os.O_RDONLY, 0644)
if err != nil {
return err
}
defer f.Close()
//safe refresh config
file := Conf.ConfigFile
if err = toml.NewDecoder(f).Decode(&Conf); err != nil {
return err
@@ -58,9 +56,14 @@ var OnRefreash = []func() error{
},
func() error {
if Conf.ClearDNSCache != "" {
ctx, _ := context.WithTimeout(context.TODO(), 5*time.Second)
if err := exec.CommandContext(ctx, "sh", "-c", Conf.ClearDNSCache).Run(); err != nil {
glog.Errorln(err)
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
defer cancel()
switch runtime.GOOS {
case "windows":
return exec.CommandContext(ctx, "cmd", "/c", Conf.ClearDNSCache).Run()
default:
return exec.CommandContext(ctx, "sh", "-c", Conf.ClearDNSCache).Run()
}
}
return nil
@@ -68,20 +71,7 @@ var OnRefreash = []func() error{
}
func init() {
flag.StringVar(&Conf.ConfigFile, "f", filepath.Dir(os.Args[0])+"/sower.toml", "config file location")
flag.StringVar(&Conf.NetType, "n", "TCP", "proxy net type (QUIC|KCP|TCP)")
flag.StringVar(&Conf.Cipher, "C", "AES_128_GCM", "cipher type (AES_128_GCM|AES_192_GCM|AES_256_GCM|CHACHA20_IETF_POLY1305|XCHACHA20_IETF_POLY1305)")
flag.StringVar(&Conf.Password, "p", "12345678", "password")
flag.StringVar(&Conf.ServerPort, "P", "5533", "server mode listen port")
flag.StringVar(&Conf.ServerAddr, "s", "", "server IP (run in client mode if set)")
flag.StringVar(&Conf.HTTPProxy, "H", "", "http proxy listen addr")
flag.StringVar(&Conf.DNSServer, "d", "114.114.114.114", "client dns server")
flag.StringVar(&Conf.ClientIP, "c", "127.0.0.1", "client dns service redirect IP")
if !flag.Parsed() {
flag.Set("logtostderr", "true")
flag.Parse()
}
initArgs()
if _, err := os.Stat(Conf.ConfigFile); os.IsNotExist(err) {
glog.Warningln("no config file has been load:", Conf.ConfigFile)
@@ -92,41 +82,12 @@ func init() {
glog.Fatalln(err)
}
}
watchConfigFile()
}
func watchConfigFile() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
glog.Fatalln(err)
}
if err := watcher.Add(filepath.Dir(Conf.ConfigFile)); err != nil {
glog.Fatalln(err)
}
go func() {
for {
select {
case event := <-watcher.Events:
if event.Op == fsnotify.Rename {
if err := watcher.Add(Conf.ConfigFile); err != nil {
glog.Errorln(err)
}
}
glog.Infof("watch %s event: %v", Conf.ConfigFile, event)
for i := range OnRefreash {
if err := OnRefreash[i](); err != nil {
glog.Errorln(err)
}
}
case err := <-watcher.Errors:
glog.Fatalln(err)
}
}
}()
}
// mu keep synchronized add rule(write), do not care read while write
var mu = &sync.Mutex{}
// AddSuggest add new domain into suggest rules
func AddSuggest(domain string) {
mu.Lock()
defer mu.Unlock()
@@ -134,20 +95,30 @@ func AddSuggest(domain string) {
Conf.Suggestions = append(Conf.Suggestions, domain)
Conf.Suggestions = util.NewReverseSecSlice(Conf.Suggestions).Sort().Uniq()
// safe write
f, err := os.OpenFile(Conf.ConfigFile+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
glog.Errorln(err)
return
}
defer f.Close()
{ // safe write
f, err := os.OpenFile(Conf.ConfigFile+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
glog.Errorln(err)
return
}
if err := toml.NewEncoder(f).ArraysWithOneElementPerLine(true).Encode(Conf); err != nil {
glog.Errorln(err)
return
if err := toml.NewEncoder(f).ArraysWithOneElementPerLine(true).Encode(Conf); err != nil {
glog.Errorln(err)
f.Close()
return
}
f.Close()
if err = os.Rename(Conf.ConfigFile+"~", Conf.ConfigFile); err != nil {
glog.Errorln(err)
return
}
}
if err = os.Rename(Conf.ConfigFile+"~", Conf.ConfigFile); err != nil {
glog.Errorln(err)
// reload config
for i := range OnRefreash {
if err := OnRefreash[i](); err != nil {
glog.Errorln(err)
}
}
}
+26
View File
@@ -0,0 +1,26 @@
// +build !windows
package conf
import (
"flag"
"os"
"path/filepath"
)
func initArgs() {
flag.StringVar(&Conf.ConfigFile, "f", filepath.Dir(os.Args[0])+"/sower.toml", "config file location")
flag.StringVar(&Conf.NetType, "n", "TCP", "proxy net type (QUIC|KCP|TCP)")
flag.StringVar(&Conf.Cipher, "C", "AES_128_GCM", "cipher type (AES_128_GCM|AES_192_GCM|AES_256_GCM|CHACHA20_IETF_POLY1305|XCHACHA20_IETF_POLY1305)")
flag.StringVar(&Conf.Password, "p", "12345678", "password")
flag.StringVar(&Conf.ServerPort, "P", "5533", "server mode listen port")
flag.StringVar(&Conf.ServerAddr, "s", "", "server IP (run in client mode if set)")
flag.StringVar(&Conf.HTTPProxy, "H", "", "http proxy listen addr")
flag.StringVar(&Conf.DNSServer, "d", "114.114.114.114", "client dns server")
flag.StringVar(&Conf.ClientIP, "c", "127.0.0.1", "client dns service redirect IP")
if !flag.Parsed() {
flag.Set("logtostderr", "true")
flag.Parse()
}
}
+145
View File
@@ -0,0 +1,145 @@
// +build windows
package conf
import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/golang/glog"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/eventlog"
"golang.org/x/sys/windows/svc/mgr"
)
const name = "sower"
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue
func initArgs() {
flag.StringVar(&Conf.ConfigFile, "f", filepath.Dir(os.Args[0])+"/sower.toml", "config file location")
install := flag.Bool("install", false, "install sower as a service")
uninstall := flag.Bool("uninstall", false, "uninstall sower from service list")
if !flag.Parsed() {
flag.Set("log_dir", filepath.Dir(os.Args[0]))
flag.Parse()
}
switch {
case *install:
mgrDo(func(m *mgr.Mgr) error {
s, err := m.OpenService(name)
if err == nil {
s.Close()
return fmt.Errorf("service %s already exists", name)
}
s, err = m.CreateService(name, os.Args[0], mgr.Config{
DisplayName: "Sower Proxy",
StartType: windows.SERVICE_AUTO_START,
})
if err != nil {
return err
}
defer s.Close()
err = eventlog.InstallAsEventCreate(name, eventlog.Error|eventlog.Warning|eventlog.Info)
if err != nil {
s.Delete()
return fmt.Errorf("SetupEventLogSource() failed: %s", err)
}
return s.Start()
})
os.Exit(0)
case *uninstall:
serviceDo(func(s *mgr.Service) error {
err := s.Delete()
if err != nil {
return err
}
return eventlog.Remove(name)
})
os.Exit(0)
default:
os.Chdir(filepath.Dir(os.Args[0]))
if active, err := svc.IsAnInteractiveSession(); err != nil {
glog.Exitf("failed to determine if we are running in an interactive session: %v", err)
} else if !active {
go func() {
elog, err := eventlog.Open(name)
if err != nil {
glog.Exitln(err)
}
defer elog.Close()
if err := svc.Run(name, &myservice{}); err != nil {
elog.Error(1, fmt.Sprintf("%s service failed: %v", name, err))
glog.Exitln(err)
}
elog.Info(1, fmt.Sprintf("winsvc.RunAsService: %s service stopped", name))
os.Exit(0)
}()
}
}
}
func serviceDo(fn func(*mgr.Service) error) {
mgrDo(func(m *mgr.Mgr) error {
s, err := m.OpenService(name)
if err != nil {
return fmt.Errorf("could not access service: %v", err)
}
defer s.Close()
return fn(s)
})
}
func mgrDo(fn func(m *mgr.Mgr) error) {
m, err := mgr.Connect()
if err != nil {
glog.Exitln(err)
}
defer m.Disconnect()
if err := fn(m); err != nil {
glog.Fatalln(err)
}
}
type myservice struct{}
func (m *myservice) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
elog, err := eventlog.Open(name)
if err != nil {
glog.Errorln(err)
return
}
defer elog.Close()
elog.Info(1, strings.Join(args, "-"))
changes <- svc.Status{State: svc.StartPending}
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
for {
c := <-r
switch c.Cmd {
case svc.Interrogate:
changes <- c.CurrentStatus
// Testing deadlock from https://code.google.com/p/winsvc/issues/detail?id=4
time.Sleep(100 * time.Millisecond)
changes <- c.CurrentStatus
case svc.Stop, svc.Shutdown:
changes <- svc.Status{State: svc.StopPending}
return
case svc.Pause:
changes <- svc.Status{State: svc.Paused, Accepts: cmdsAccepted}
case svc.Continue:
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
default:
elog.Error(1, fmt.Sprintf("unexpected control request #%d", c))
}
}
}
+13 -2
View File
@@ -8,7 +8,7 @@ dns_server="" # Keep empty for dynamic setting from net env
client_ip="127.0.0.1" # listen the IP, dns target is the IP
# clear_dns_cache="killall -HUP mDNSResponder"
blocklist=[
"**.google.com", # google
"**.google.*", # google
"**.goo.gl",
"**.googleusercontent.com",
"**.googleapis.com",
@@ -18,19 +18,30 @@ blocklist=[
"**.ggpht.com",
"**.googlevideo.com",
"**.facebook.com", # facebook
"**.xx.fbcdn.net",
"**.fbcdn.net",
"**.twitter.com", # twitter
"**.twimg.com",
"**.blogspot.com", # blogspot
"**.appspot.com",
"**.wikipedia.org", # wikipeida
"*.cloudfront.net",
"**.amazon.com",
"**.amazonaws.com",
"*.githubusercontent.com",
"*.github.*",
]
whitelist=[
"iamp.*.*.*",
"iamp.*.*",
"**.mail.*.*",
"**.mail.*.*.*",
"imap-mail.outlook.com",
"**.qq.com",
"**.baidu.com",
"*.aliyun.com",
"**.cn",
"**.icloud.com",
"**.163.com",
"**.weiyun.com",
]
verbose=0
+43 -12
View File
@@ -8,27 +8,40 @@ succ_message(){
echo
echo ======== Installed sower to your system ========
echo The config file is: /usr/local/etc/sower.toml
echo please set 127.0.0.1 as the first domain name server manually.
echo please set $IP as the first domain name server manually.
}
# main logic
VERSION="$(curl -s "https://api.github.com/repos/wweir/sower/releases/latest" | awk -F '"' '/tag_name/{printf $4}')"
case "$(uname -s)" in
"Darwin")
printf "Please enter remote server adddress: "
read ADDRESS
echo
curl -SLf https://github.com/wweir/sower/releases/download/$VERSION/sower_darwin_amd64.tar.gz | tar xzv
mv sower /usr/local/bin/
sudo mkdir -p /usr/local/bin/
sudo mv sower /usr/local/bin/
if [[ -r /usr/local/etc/sower.toml ]]; then
echo The config file already exists, keep the original file
else
printf "Please enter remote server adddress: "
read ADDRESS
printf "Please enter remote server password (default: 12345678): "
read PASSWORD
if [[ -z $PASSWORD ]]; then
PASSWORD="12345678"
fi
printf "Please enter which IP do you wanna listen (default: 127.0.0.1):"
read IP
if [[ -z $IP ]]; then
IP="127.0.0.1"
fi
echo
sed -i~ "s/# server_addr=\"remote-server/server_addr=\"$ADDRESS/" sower.toml
sed -i~ "s/client_ip=\"127.0.0.1\"/client_ip=\"$IP\"/" sower.toml
sed -i~ "s/# clear_dns_cache/clear_dns_cache/" sower.toml
mv sower.toml /usr/local/etc/
sed -i~ "s%bin/sower%bin/sower -p $PASSWORD%" sower-server.service
sudo mkdir -p /usr/local/etc/
sudo mv sower.toml /usr/local/etc/
fi
echo
@@ -51,10 +64,6 @@ case "$(uname -s)" in
case "$SIDE" in
"c")
printf "Please enter remote server adddress: "
read ADDRESS
echo
curl -SLf https://github.com/wweir/sower/releases/download/$VERSION/sower_linux_amd64.tar.gz | tar xzv
sudo mv sower /usr/local/bin/
@@ -62,7 +71,22 @@ case "$(uname -s)" in
if [[ -r /usr/local/etc/sower.toml ]]; then
echo The config file already exists, keep the original file
else
printf "Please enter remote server adddress: "
read ADDRESS
printf "Please enter remote server password (default: 12345678): "
read PASSWORD
if [[ -z $PASSWORD ]]; then
PASSWORD="12345678"
fi
printf "Please enter which IP do you wanna listen (default: 127.0.0.1):"
read IP
if [[ -z $IP ]]; then
IP="127.0.0.1"
fi
echo
sed -i~ "s/# server_addr=\"remote-server/server_addr=\"$ADDRESS/" sower.toml
sed -i~ "s/client_ip=\"127.0.0.1\"/client_ip=\"$IP\"/" sower.toml
sudo mv sower.toml /usr/local/etc/
fi
@@ -74,8 +98,15 @@ case "$(uname -s)" in
"s")
curl -SLf https://github.com/wweir/sower/releases/download/$VERSION/sower_linux_amd64.tar.gz | tar xzv
printf "Please enter remote server password (default: 12345678): "
read PASSWORD
echo
if [[ -z $PASSWORD ]]; then
PASSWORD="12345678"
fi
sudo mv sower /usr/local/bin/
sed -i~ "s%bin/sower%bin/sower -p $PASSWORD%" sower-server.service
sudo mv sower-server.service /etc/systemd/system/
sudo systemctl enable sower-server
sudo systemctl start sower-server
+9 -3
View File
@@ -3,9 +3,10 @@ package dns
import (
"math/rand"
"net"
"runtime"
"github.com/golang/glog"
"github.com/wweir/netboot/dhcp4"
"go.universe.tf/netboot/dhcp4"
)
var xid = make([]byte, 4)
@@ -19,11 +20,16 @@ func GetDefaultDNSServer() string {
dhcp4.OptRequestedOptions: []byte{byte(dhcp4.OptDNSServers)},
}
NewConn := dhcp4.NewConn
if runtime.GOOS == "linux" {
NewConn = dhcp4.NewSnooperConn
}
ifaces := mustGetInterfaces()
for _, iface := range ifaces {
conn, err := dhcp4.NewConn(iface.IP.String() + ":68")
conn, err := NewConn(iface.IP.String() + ":68")
if err != nil { // maybe in use
glog.V(1).Infoln(err)
glog.Errorln(err)
continue
}
defer conn.Close()
+4 -5
View File
@@ -3,18 +3,17 @@ package dns
import "testing"
func TestGetDefaultDNSServer(t *testing.T) {
t.Skip("for net env")
t.Skip("skip for some enviroment not support dhcp")
tests := []struct {
name string
want string
}{{
"",
"192.168.1.1",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetDefaultDNSServer(); got != tt.want {
t.Errorf("GetDefaultDNSServer() = %v, want %v", got, tt.want)
if got := GetDefaultDNSServer(); got == "" {
t.Errorf("GetDefaultDNSServer() return empty")
}
})
}
+49 -39
View File
@@ -3,26 +3,27 @@ package dns
import (
"net"
"strings"
"sync/atomic"
"time"
"github.com/golang/glog"
"github.com/miekg/dns"
mem "github.com/wweir/mem-go"
"github.com/wweir/sower/conf"
"github.com/wweir/sower/util"
)
const colon = byte(':')
func StartDNS(dnsServer, listenIP string) {
ip := net.ParseIP(listenIP)
suggest := &intelliSuggest{listenIP, 2 * time.Second, []string{"80", "443"}}
suggest := &intelliSuggest{listenIP, 800 * time.Millisecond}
mem.DefaultCache = mem.New(time.Hour)
var dhcpCh chan struct{}
dhcpCh := make(chan struct{})
if dnsServer != "" {
dnsServer = net.JoinHostPort(dnsServer, "53")
} else {
dhcpCh = make(chan struct{})
go func() {
for {
<-dhcpCh
@@ -35,6 +36,7 @@ func StartDNS(dnsServer, listenIP string) {
glog.Infoln("set dns server to", host)
}
}()
dhcpCh <- struct{}{}
}
dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
@@ -65,17 +67,12 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer
dhcpCh chan struct{}, ipNet net.IP, suggest *intelliSuggest) {
inWriteList := whiteList.Match(domain)
if !inWriteList && (blockList.Match(domain) || suggestList.Match(domain)) {
glog.V(2).Infof("match %s suss", domain)
w.WriteMsg(localA(r, domain, ipNet))
return
}
if !inWriteList {
go mem.Remember(suggest, domain)
}
msg, err := dns.Exchange(r, dnsServer)
if err != nil && dhcpCh != nil {
select {
@@ -83,6 +80,12 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer
default:
}
}
// trigger suggest logic except dhcp dns server error
if !inWriteList {
go mem.Remember(suggest, domain)
}
if msg == nil { // expose any response except nil
glog.V(1).Infof("get dns of %s fail: %s", domain, err)
return
@@ -93,11 +96,10 @@ func matchAndServe(w dns.ResponseWriter, r *dns.Msg, domain, listenIP, dnsServer
type intelliSuggest struct {
listenIP string
timeout time.Duration
ports []string
}
func (i *intelliSuggest) GetOne(domain interface{}) (iface interface{}, e error) {
iface = struct{}{}
iface, e = struct{}{}, nil
// kill deadloop, for ugly wildcard setting dns setting
addr := strings.TrimSuffix(domain.(string), ".")
@@ -105,36 +107,44 @@ func (i *intelliSuggest) GetOne(domain interface{}) (iface interface{}, e error)
return
}
for _, port := range i.ports {
// give local dial a hand, make it not so easy to be added into suggestions
<-util.HTTPPing(net.JoinHostPort(addr, port), addr, i.timeout/50)
localCh := util.HTTPPing(net.JoinHostPort(addr, port), addr, i.timeout)
remoteCh := util.HTTPPing(net.JoinHostPort(i.listenIP, port), addr, i.timeout)
select {
case err := <-localCh:
if err == nil {
glog.V(2).Infoln("PING", addr, "local first, succ")
continue
}
if e := <-remoteCh; e != nil {
glog.V(2).Infoln("PING", addr, "local first, all fail:", err)
continue
}
glog.V(2).Infoln("PING", addr, "local first, remote succ")
conf.AddSuggest(addr)
case err := <-remoteCh:
if err != nil {
glog.V(2).Infoln("PING", addr, "remote first, fail:", err)
continue
}
glog.V(2).Infoln("PING", addr, "remote first, succ")
conf.AddSuggest(addr)
var (
pings = []struct {
viaAddr string
port Port
}{
{addr, Http},
{addr, Https},
{i.listenIP, Http},
{i.listenIP, Https},
}
half = int32(len(pings) / 2)
score = new(int32)
)
for idx := range pings {
go func(idx int) {
err := HTTPPing(pings[idx].viaAddr, addr, pings[idx].port, i.timeout)
if err != nil {
// local ping fail
if pings[idx].viaAddr == addr {
atomic.AddInt32(score, 1)
}
} else {
// remote ping succ
if pings[idx].viaAddr == i.listenIP {
atomic.AddInt32(score, 1)
glog.Infof("added suggest domain: %s", addr)
return
// local ping took longger than remote
} else if atomic.LoadInt32(score) >= half {
atomic.AddInt32(score, 1)
}
}
if atomic.LoadInt32(score) > half {
atomic.StoreInt32(score, 0) // avoid redo add action
conf.AddSuggest(addr)
glog.Infof("added suggest domain: %s", addr)
}
}(idx)
}
return
}
+36 -26
View File
@@ -1,4 +1,4 @@
package util
package dns
import (
"bytes"
@@ -10,36 +10,15 @@ import (
)
// HTTPPing try connect to a http(s) server with domain though the http addr
func HTTPPing(tcpAddr, domain string, timeout time.Duration) <-chan error {
errCh := make(chan error)
go func() {
errCh <- httpPing(tcpAddr, domain, timeout)
}()
return errCh
}
func httpPing(tcpAddr, domain string, timeout time.Duration) error {
conn, err := net.DialTimeout("tcp", tcpAddr, timeout)
func HTTPPing(viaHost, domain string, port Port, timeout time.Duration) (err error) {
conn, err := net.DialTimeout("tcp", port.JoinAddr(viaHost), timeout)
if err != nil {
return err
}
defer conn.Close()
host, port, err := net.SplitHostPort(tcpAddr)
if err != nil {
return err
}
var msg []byte
switch port {
case ":80":
msg = []byte("TRACE / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n")
case ":443":
msg = NewClientHelloSNIMsg(domain)
}
conn.SetDeadline(time.Now().Add(timeout))
if _, err = conn.Write(msg); err != nil {
if _, err = conn.Write(port.pingMsg(domain)); err != nil {
return err
}
@@ -47,12 +26,43 @@ func httpPing(tcpAddr, domain string, timeout time.Duration) error {
// err -> io.EOF: no such domain or connection refused
// err -> timeout: tcp package has been dropped
_, err = conn.Read(make([]byte, 1))
if err == io.EOF && host == domain {
if err == io.EOF && viaHost == domain {
return nil
}
return err
}
// Port ==========================
type Port uint16
const (
Http Port = iota
Https
)
func (p Port) JoinAddr(addr string) string {
switch p {
case Http:
return addr + ":80"
case Https:
return addr + ":443"
default:
panic("invalid port")
}
}
func (p Port) pingMsg(domain string) []byte {
switch p {
case Http:
return []byte("TRACE / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n")
case Https:
return NewClientHelloSNIMsg(domain)
default:
panic("invalid port")
}
}
// SNI ==========================
type clientHelloSNI struct {
ContentType uint8
Version uint16
+3 -1
View File
@@ -23,19 +23,21 @@ func init() {
suggestList = loadRules("suggest", conf.Conf.Suggestions)
whiteList = loadRules("white", conf.Conf.WhiteList)
whiteList.Add(host)
glog.V(1).Infoln("load config")
conf.OnRefreash = append(conf.OnRefreash, func() error {
blockList = loadRules("block", conf.Conf.BlockList)
suggestList = loadRules("suggest", conf.Conf.Suggestions)
whiteList = loadRules("white", conf.Conf.WhiteList)
whiteList.Add(host)
glog.V(1).Infoln("reload config")
return nil
})
}
func loadRules(name string, list []string) *util.Node {
rule := util.NewNodeFromRules(".", list...)
glog.V(2).Infof("load %s rule:\n%s", name, rule)
glog.V(3).Infof("load %s rule:\n%s", name, rule)
return rule
}
+8 -9
View File
@@ -1,27 +1,26 @@
module github.com/wweir/sower
go 1.12
require (
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // lock for quic
github.com/cheekybits/genny v1.0.0 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/hashicorp/golang-lru v0.5.0 // indirect
github.com/hashicorp/golang-lru v0.5.1 // indirect
github.com/klauspost/cpuid v1.2.0 // indirect
github.com/klauspost/reedsolomon v1.8.0 // indirect
github.com/klauspost/reedsolomon v1.9.0 // indirect
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f // indirect
github.com/lucas-clemente/quic-go v0.10.1
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced // indirect
github.com/miekg/dns v1.1.3
github.com/miekg/dns v1.1.4
github.com/pelletier/go-toml v1.2.0
github.com/pkg/errors v0.8.1
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect
github.com/tjfoc/gmsm v1.0.1 // indirect
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f // indirect
github.com/wweir/fsnotify v1.4.8
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296
github.com/wweir/netboot v0.0.2
github.com/xtaci/kcp-go v5.0.7+incompatible
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e // indirect
go.universe.tf/netboot v0.0.0-20190215013330-01f30467ac8e
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25
)
+39 -19
View File
@@ -1,46 +1,66 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 h1:x17NvoJaphEzay72TFej4OSSsgu3xRYBLkbIwdofS/4=
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/google/go-cmp v0.1.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
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.8.0 h1:lvvOkvk64cE1EGbBIgFk7WSOOsI1GexpuLiT7zjab6g=
github.com/klauspost/reedsolomon v1.8.0/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/klauspost/reedsolomon v1.9.0 h1:usyTY5K7D2B6WOHn2jmpB7ky8Qom96mShZmmq3OW4JU=
github.com/klauspost/reedsolomon v1.9.0/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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.1 h1:ipcMmYP9RT+b1YytOKGUY1qndxPGOczVEQkAVz3CZrs=
github.com/lucas-clemente/quic-go v0.10.1/go.mod h1:wuD+2XqEx8G9jtwx5ou2BEYBsE+whgQmlj0Vz/77PrY=
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced h1:zqEC1GJZFbGZA0tRyNZqRjep92K5fujFtFsu5ZW7Aug=
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58=
github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM=
github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/magiconair/properties v1.7.4/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/afero v1.0.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b h1:mnG1fcsIB1d/3vbkBak2MM0u+vhGhlQwpeimUi7QncM=
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tjfoc/gmsm v1.0.1 h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU=
github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f h1:QatZ4lsJBY3x1+Imst9g95+vUl7m52dqM9Pi4aSMW8w=
github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f/go.mod h1:BNLmYJ8oMJPIPpNx5968jCyUhwEU1XT3YsuOqtbo5qo=
github.com/wweir/fsnotify v1.4.8 h1:zxOoqwE5p91F3rmcYLQheoSeTlIVqwi2b5T7UlpElWE=
github.com/wweir/fsnotify v1.4.8/go.mod h1:4GuxIc23DXfJI1/LhBXG5eE/wJ4CzL+kk5M7woxVprc=
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296 h1:/HkUfg+ZMx/tNdnyJdVlhyv+xO3A7ZlpfL9nFLWLYcc=
github.com/wweir/mem-go v0.0.0-20190109100331-8673ab596296/go.mod h1:k7rjBGWoJ+JKwvfe8juAX0zgybjo/Yo3JGkca5f/06s=
github.com/wweir/netboot v0.0.2 h1:DFuNd97kxzgblExEKn4Nqf1du0m9qUnaTQ70rFgIjLU=
github.com/wweir/netboot v0.0.2/go.mod h1:p/WOnPHdqwgAI6YLEfdmwjwutbc/zDZ7EojAHlXLi4s=
github.com/xtaci/kcp-go v5.0.7+incompatible h1:zs9tc8XRID0m+aetu3qPWZFyRt2UIMqbXIBgw+vcnlE=
github.com/xtaci/kcp-go v5.0.7+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
go.universe.tf/netboot v0.0.0-20190215013330-01f30467ac8e/go.mod h1:SayXxCfNj1vDO8eF7GpY1xEZ8px5LfHUSr+uJJMcDTo=
golang.org/x/crypto v0.0.0-20180206190813-d9133f546934/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25 h1:jsG6UpNLt9iAsb0S2AGW28DveNzzgmbXR+ENoPjUeIU=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180202180947-2fb46b16b8dd h1:sFXnfxrhbeCXDiKa6Ra98LxiHoUWSHs9AKOxFURy5pY=
golang.org/x/net v0.0.0-20180202180947-2fb46b16b8dd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20180202135801-37707fdb30a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.0.0-20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+10 -5
View File
@@ -31,15 +31,20 @@ func NewClient(netType string) Client {
func StartClient(netType, server, cipher, password, listenIP string) {
connCh := listenLocal(listenIP, []string{"80", "443"})
client := NewClient(netType)
if addr, err := net.ResolveTCPAddr("tcp", server); err != nil {
glog.Fatalln(err)
} else {
server = addr.String()
}
resolved := false
glog.Infoln("Client started.")
for {
conn := <-connCh
if !resolved {
if addr, err := net.ResolveTCPAddr("tcp", server); err != nil {
glog.Errorln(err)
} else {
server = addr.String()
resolved = true
}
}
glog.V(1).Infof("new conn from (%s) to (%s)", conn.RemoteAddr(), server)
rc, err := client.Dial(server)
+10 -5
View File
@@ -14,15 +14,20 @@ import (
func StartHttpProxy(netType, server, cipher, password, addr string) {
client := NewClient(netType)
if addr, err := net.ResolveTCPAddr("tcp", server); err != nil {
glog.Fatalln(err)
} else {
server = addr.String()
}
resolved := false
srv := &http.Server{
Addr: addr,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !resolved {
if addr, err := net.ResolveTCPAddr("tcp", server); err != nil {
glog.Errorln(err)
} else {
server = addr.String()
resolved = true
}
}
if r.Method == http.MethodConnect {
httpsProxy(w, r, client, server, cipher, password)
} else {
+3 -4
View File
@@ -18,10 +18,9 @@ type client struct {
func NewClient() *client {
return &client{
conf: &quic.Config{
HandshakeTimeout: 5 * time.Second,
MaxIncomingStreams: 1024,
KeepAlive: true,
IdleTimeout: 5 * time.Minute,
HandshakeTimeout: time.Second,
KeepAlive: true,
IdleTimeout: time.Minute,
},
}
}
-4
View File
@@ -2,7 +2,6 @@ package quic
import (
"net"
"time"
"github.com/golang/glog"
quic "github.com/lucas-clemente/quic-go"
@@ -16,10 +15,7 @@ type server struct {
func NewServer() *server {
return &server{
conf: &quic.Config{
HandshakeTimeout: 5 * time.Second,
MaxIncomingStreams: 1024,
KeepAlive: true,
IdleTimeout: 5 * time.Minute,
},
}
}
+6 -2
View File
@@ -88,10 +88,14 @@ func (n *node) matchSecs(secs []string, fuzzNode bool) bool {
}
if n, ok := n.node[secs[length-1]]; ok {
return n.matchSecs(secs[:length-1], false)
if n.matchSecs(secs[:length-1], false) {
return true
}
}
if n, ok := n.node["*"]; ok {
return n.matchSecs(secs[:length-1], true)
if n.matchSecs(secs[:length-1], true) {
return true
}
}
if _, ok := n.node["**"]; ok {
return true
+6 -4
View File
@@ -39,11 +39,12 @@ func TestNode_Match(t *testing.T) {
},
}, {
"fuzz2",
NewNodeFromRules(".", "a.*.cc"),
NewNodeFromRules(".", "a.*.cc", "c.wweir.*"),
[]test{
{"wweir.cc", false},
{"a.wweir.cc", true},
{"b.wweir.cc", false},
{"c.wweir.cc", true},
},
}, {
"fuzz3",
@@ -56,13 +57,14 @@ func TestNode_Match(t *testing.T) {
},
}, {
"fuzz4",
NewNodeFromRules(".", "**.cc", "a.**.com"),
NewNodeFromRules(".", "**.cc", "a.**.com", "**.wweir.*"),
[]test{
{"wweir.cc", true},
{"a.wweir.cc", true},
{"a.b.wweir.cc", true},
{"a.wweir.com", true},
{"b.wweir.com", false},
{"a.fuzz.com", true},
{"b.fuzz.com", false},
{"www.wweir.com", true},
},
}}
for _, tt := range tests {