Skip to content

Commit

Permalink
Refactor for tls 1.3 esni
Browse files Browse the repository at this point in the history
  • Loading branch information
wweir committed Mar 19, 2020
1 parent bcc6d7c commit c0f39fc
Show file tree
Hide file tree
Showing 32 changed files with 494 additions and 858 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,16 @@ There are 3 kinds of proxy solutions, they are HTTP(S)_PROXY / DNS-based proxy /
An HTTP(S)_PROXY listening on `:8080` is set by default if you run sower as client mode.

### DNS-based proxy
You can set the `serve_ip` field in the `dns` section in the configuration file to start the DNS-based proxy. You should also set the value of `serve_ip` as your default DNS in OS.
**DNS-based** solution is not recommanded now, for incompatible with TLS 1.3 esni extention.

You can set the `dns_serve_ip` field in the configuration file to start the DNS-based proxy. You should also set the value of `dns_upstream` as your default DNS in OS.

If you want to enjoy the full experience provided by the sower, you can take sower as your private DNS on a long-running server and set it as your default DNS in your router.

### port-forward
The port-forward can be only setted in configuration file, you can set it in section `client.router.port_mapping`, eg:
The port-forward can be only setted in configuration file, you can set it in section `client.port_mapping`, eg:
``` toml
[client.router.port_mapping]
[client.port_mapping]
":2222"="aa.bb.cc:22"
```

Expand Down
100 changes: 36 additions & 64 deletions conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,25 @@ package conf
import (
"flag"
"os"
"time"

toml "github.com/pelletier/go-toml"
"github.com/wweir/sower/util"
"github.com/wweir/utils/log"
)

type client struct {
Address string `toml:"address"`

HTTPProxy struct {
Address string `toml:"address"`
} `toml:"http_proxy"`

DNS struct {
ServeIP string `toml:"serve_ip"`
Upstream string `toml:"upstream"`
FlushCmd string `toml:"flush_cmd"`
} `toml:"dns"`
Address string `toml:"address"`
HTTPProxy string `toml:"http_proxy"`
DNSServeIP string `toml:"dns_serve_ip"`
DNSUpstream string `toml:"dns_upstream"`
PortForward map[string]string `toml:"port_forward"`

Router struct {
PortMapping map[string]string `toml:"port_mapping"`
DetectLevel int `toml:"detect_level"`
DetectTimeout string `toml:"detect_timeout"`

ProxyList []string `toml:"proxy_list"`
DirectList []string `toml:"direct_list"`
DynamicList map[string]int `toml:"dynamic_list"` // toml has a bug with dot
directRules *util.Node
proxyRules *util.Node
dynamicRules *util.Node
DetectLevel int `toml:"detect_level"`
DetectTimeout string `toml:"detect_timeout"`

ProxyList []string `toml:"proxy_list"`
DirectList []string `toml:"direct_list"`
DynamicList []string `toml:"dynamic_list"`
} `toml:"router"`
}
type server struct {
Expand All @@ -48,26 +36,24 @@ var (

Server = server{}
Client = client{}
conf = struct {
file string
Server *server `toml:"server"`
Client *client `toml:"client"`
}{"", &Server, &Client}
Conf = struct {
file string
Password string `toml:"password"`
Server *server `toml:"server"`
Client *client `toml:"client"`
}{"", "", &Server, &Client}
flushCh = make(chan struct{})
Password string
installCmd string
uninstallFlag bool
)

func init() {
flag.StringVar(&Password, "password", "", "password")
flag.StringVar(&Conf.Password, "password", "", "password")
flag.StringVar(&Server.Upstream, "s", "", "upstream http service, eg: 127.0.0.1:8080")
flag.StringVar(&Server.CertFile, "s_cert", "", "tls cert file, gen cert from letsencrypt if empty")
flag.StringVar(&Server.KeyFile, "s_key", "", "tls key file, gen cert from letsencrypt if empty")
flag.StringVar(&Client.Address, "c", "", "remote server domain, eg: aa.bb.cc, socks5h://127.0.0.1:1080")
flag.StringVar(&Client.HTTPProxy.Address, "http_proxy", ":8080", "http proxy, empty to disable")
flag.StringVar(&Client.DNS.ServeIP, "dns_ip", "", "upstream dns, eg: 127.0.0.1, disable dns proxy if empty")
flag.StringVar(&Client.DNS.Upstream, "dns_upstream", "", "dns relay server ip, dynamic detect if empty")
flag.StringVar(&Client.HTTPProxy, "http_proxy", ":8080", "http proxy, empty to disable")
flag.IntVar(&Client.Router.DetectLevel, "level", 2, "dynamic rule detect level: 0~4")
flag.StringVar(&Client.Router.DetectTimeout, "timeout", "300ms", "dynamic rule detect timeout")
flag.BoolVar(&uninstallFlag, "uninstall", false, "uninstall service")
Expand All @@ -85,23 +71,14 @@ func init() {
os.Exit(0)
}

var err error
defer func() {
if timeout, err = time.ParseDuration(Client.Router.DetectTimeout); err != nil {
log.Fatalw("parse dynamic detect timeout", "val", Client.Router.DetectTimeout, "err", err)
}

log.Infow("start", "version", version, "date", date, "conf", &conf)
passwordData = []byte(Password)
}()

if conf.file == "" {
defer log.Infow("starting", "config", &Conf)
if Conf.file == "" {
return
}

for i := range loadConfigFns {
if err = loadConfigFns[i].fn(); err != nil {
log.Fatalw("load config", "config", conf.file, "step", loadConfigFns[i].step, "err", err)
if err := loadConfigFns[i].fn(); err != nil {
log.Fatalw("load config", "config", Conf.file, "step", loadConfigFns[i].step, "err", err)
}
}

Expand All @@ -113,45 +90,40 @@ var loadConfigFns = []struct {
step string
fn func() error
}{{"load_config", func() error {
f, err := os.OpenFile(conf.file, os.O_RDONLY, 0644)
f, err := os.OpenFile(Conf.file, os.O_RDONLY, 0644)
if err != nil {
return err
}
defer f.Close()

Client.Router.DynamicList = map[string]int{}
return toml.NewDecoder(f).Decode(&conf)

}}, {"load_rules", func() error {
Client.Router.directRules = util.NewNodeFromRules(Client.Router.DirectList...)
Client.Router.proxyRules = util.NewNodeFromRules(Client.Router.ProxyList...)
return nil

}}, {"flush_dns", func() error {
if Client.DNS.FlushCmd != "" {
return execute(Client.DNS.FlushCmd)
}
return nil
return toml.NewDecoder(f).Decode(&Conf)
}}}

func PersistRule(domain string) {
Client.Router.DynamicList = append(Client.Router.DynamicList, domain)
select {
case flushCh <- struct{}{}:
default:
}
}
func flushConfDaemon() {
for range flushCh {
// safe write file
if conf.file != "" {
f, err := os.OpenFile(conf.file+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if Conf.file != "" {
f, err := os.OpenFile(Conf.file+"~", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Errorw("flush config", "step", "flush", "err", err)
continue
}

if err := toml.NewEncoder(f).ArraysWithOneElementPerLine(true).Encode(conf); err != nil {
if err := toml.NewEncoder(f).ArraysWithOneElementPerLine(true).Encode(&Conf); err != nil {
log.Errorw("flush config", "step", "flush", "err", err)
f.Close()
continue
}
f.Close()

if err = os.Rename(conf.file+"~", conf.file); err != nil {
if err = os.Rename(Conf.file+"~", Conf.file); err != nil {
log.Errorw("flush config", "step", "flush", "err", err)
continue
}
Expand Down
5 changes: 2 additions & 3 deletions conf/conf_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ const svcFile = `<?xml version="1.0" encoding="UTF-8"?>
</plist>`

func Init() {
flag.StringVar(&conf.file, "f", "", "config file, rewrite all other parameters if set")
flag.StringVar(&Client.DNS.FlushCmd, "flush_dns", "pkill mDNSResponder || true", "flush dns command")
flag.StringVar(&installCmd, "install", "", "install service with cmd, eg: '-f /etc/sower/sower.toml'")
flag.StringVar(&Conf.file, "f", "", "config file, rewrite all other parameters if set")
flag.StringVar(&installCmd, "install", "", "install service with cmd, eg: '-f /etc/sower.toml'")
}

func install() {
Expand Down
5 changes: 2 additions & 3 deletions conf/conf_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ RestartSec=3
Restart=on-failure`

func Init() {
flag.StringVar(&conf.file, "f", "", "config file, rewrite all other parameters if set")
flag.StringVar(&Client.DNS.FlushCmd, "flush_dns", "", "flush dns command")
flag.StringVar(&installCmd, "install", "", "install service with cmd, eg: '-f /etc/sower/sower.toml'")
flag.StringVar(&Conf.file, "f", "", "config file, rewrite all other parameters if set")
flag.StringVar(&installCmd, "install", "", "install service with cmd, eg: '-f /etc/sower.toml'")
}
func install() {
execFile, err := filepath.Abs(os.Args[0])
Expand Down
7 changes: 3 additions & 4 deletions conf/conf_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ var execFile, _ = filepath.Abs(os.Args[0])
var execDir, _ = filepath.Abs(filepath.Dir(execFile))

func Init() {
flag.StringVar(&conf.file, "f", filepath.Join(execDir, "sower.toml"), "config file, rewrite all other parameters if set")
flag.StringVar(&Conf.file, "f", filepath.Join(execDir, "sower.toml"), "config file, rewrite all other parameters if set")
flag.StringVar(&installCmd, "install", "", "install service with cmd")
flag.StringVar(&Client.DNS.FlushCmd, "flush_dns", "ipconfig /flushdnss", "flush dns command")
flag.Parse()

switch {
Expand Down Expand Up @@ -151,7 +150,7 @@ func execute(cmd string) error {
defer cancel()

var cmds []string
for _, cmd := range strings.Split(Client.DNS.FlushCmd, " ") {
for _, cmd := range strings.Split(cmd, " ") {
if cmd == "" {
continue
}
Expand All @@ -168,7 +167,7 @@ func execute(cmd string) error {
command := exec.CommandContext(ctx, cmds[0], cmds[1:]...)
command.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
if out, err := command.CombinedOutput(); err != nil {
return fmt.Errorf("cmd: %s, output: %s, err: %w", Client.DNS.FlushCmd, out, err)
return fmt.Errorf("cmd: %s, output: %s, err: %w", cmd, out, err)
}
return nil
}
Loading

0 comments on commit c0f39fc

Please sign in to comment.