Skip to content

Commit

Permalink
Migrate to white list match
Browse files Browse the repository at this point in the history
  • Loading branch information
wweir committed Apr 16, 2020
1 parent 78b6d4d commit 396b08c
Show file tree
Hide file tree
Showing 20 changed files with 353 additions and 155 deletions.
86 changes: 36 additions & 50 deletions conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,20 @@ import (
"github.com/wweir/utils/log"
)

type client struct {
type Client struct {
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 {
DetectLevel int `toml:"detect_level"`
DetectTimeout string `toml:"detect_timeout"`

DetectLevel int `toml:"detect_level"`
ProxyList []string `toml:"proxy_list"`
DirectList []string `toml:"direct_list"`
DynamicList []string `toml:"dynamic_list"`
} `toml:"router"`
}
type server struct {
type Server struct {
Upstream string `toml:"upstream"`
CertFile string `toml:"cert_file"`
KeyFile string `toml:"key_file"`
Expand All @@ -37,82 +34,71 @@ type server struct {
var (
version, date string

installCmd string
execFile, _ = os.Executable()
execDir, _ = filepath.Abs(filepath.Dir(execFile))
// Conf full config, include common and server / client
Conf = struct {
conf = struct {
file string
Password string `toml:"password"`
Server server `toml:"server"`
Client client `toml:"client"`
Client Client `toml:"client"`
Server Server `toml:"server"`
}{}
)

func init() {
flag.StringVar(&Conf.Password, "password", "", "password")
flag.StringVar(&Conf.Server.Upstream, "s", "", "upstream http service, eg: 127.0.0.1:8080")
flag.StringVar(&Conf.Server.CertFile, "s_cert", "", "tls cert file, gen cert from letsencrypt if empty")
flag.StringVar(&Conf.Server.KeyFile, "s_key", "", "tls key file, gen cert from letsencrypt if empty")
flag.StringVar(&Conf.Client.Address, "c", "", "remote server domain, eg: aa.bb.cc, socks5h://127.0.0.1:1080")
flag.StringVar(&Conf.Client.HTTPProxy, "http_proxy", ":8080", "http proxy, empty to disable")
flag.IntVar(&Conf.Client.Router.DetectLevel, "level", 2, "dynamic rule detect level: 0~4")
flag.StringVar(&Conf.Client.Router.DetectTimeout, "timeout", "300ms", "dynamic rule detect timeout")
uninstallFlag := flag.Bool("uninstall", false, "uninstall service")
_init() // execute platform init logic
func Init() (*Client, *Server, string) {
beforeInitFlag()
flag.StringVar(&conf.Password, "password", "", "password")
flag.StringVar(&conf.Server.Upstream, "s", "", "upstream http service, eg: 127.0.0.1:8080")
flag.StringVar(&conf.Server.CertFile, "s_cert", "", "tls cert file, gen cert from letsencrypt if empty")
flag.StringVar(&conf.Server.KeyFile, "s_key", "", "tls key file, gen cert from letsencrypt if empty")
flag.StringVar(&conf.Client.Address, "c", "", "remote server domain, eg: aa.bb.cc, socks5h://127.0.0.1:1080")
flag.StringVar(&conf.Client.HTTPProxy, "http_proxy", ":8080", "http proxy, empty to disable")
flag.IntVar(&conf.Client.Router.DetectLevel, "level", 2, "dynamic rule detect level: 0~4")

if !flag.Parsed() {
flag.Parse()
}
switch {
case *uninstallFlag:
uninstall()
os.Exit(0)
case installCmd != "":
install()
os.Exit(0)
default:
runAsService()
}
afterInitFlag()

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

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

// refreshFns will be executed while init and write new config
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()

return toml.NewDecoder(f).Decode(&Conf)
return toml.NewDecoder(f).Decode(&conf)
}}}

// flushCh to avoid parallel persist
var flushCh = make(chan struct{})
var flushOnce = sync.Once{}

// PersistRule persist dynamic rule into config file
// PersistRule persist rule into config file
func PersistRule(domain string) {
flushOnce.Do(func() {
go flushConfDaemon()
})

log.Infow("persist dynamic rule into config", "domain", domain)
Conf.Client.Router.DynamicList = append(Conf.Client.Router.DynamicList, domain)
log.Infow("persist direct rule into config", "domain", domain)
conf.Client.Router.DirectList = append(conf.Client.Router.DirectList, domain)
select {
case flushCh <- struct{}{}:
default:
Expand All @@ -121,34 +107,34 @@ func PersistRule(domain string) {
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
}

Conf.Client.Router.DynamicList =
util.NewReverseSecSlice(Conf.Client.Router.DynamicList).Sort().Uniq()
conf.Client.Router.DirectList =
util.NewReverseSecSlice(conf.Client.Router.DirectList).Sort().Uniq()

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 stat, err := os.Stat(Conf.file); err != nil {
log.Warnw("get file stat", "file", Conf.file, "err", err)
if stat, err := os.Stat(conf.file); err != nil {
log.Warnw("get file stat", "file", conf.file, "err", err)
} else {
// There is no common way to transfer ownership for a file
// cross-platform. Drop the ownership support but file mod.
if err = os.Chmod(Conf.file+"~", stat.Mode()); err != nil {
log.Warnw("set file mod", "file", Conf.file+"~", "err", err)
if err = os.Chmod(conf.file+"~", stat.Mode()); err != nil {
log.Warnw("set file mod", "file", conf.file+"~", "err", err)
}
}

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
27 changes: 21 additions & 6 deletions conf/conf_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ const svcFile = `<?xml version="1.0" encoding="UTF-8"?>
</dict>
</plist>`

var ConfigDir = ""
var (
ConfigDir = ""
installCmd = ""
uninstallFlag = false
)

func _init() {
func beforeInitFlag() {
if _, err := os.Stat(execDir + "/sower.toml"); err == nil {
ConfigDir = execDir
} else {
Expand All @@ -46,23 +50,34 @@ func _init() {
}

if _, err := os.Stat(ConfigDir + "/sower.toml"); err != nil {
flag.StringVar(&Conf.file, "f", "", "config file, rewrite all other parameters if set")
flag.StringVar(&conf.file, "f", "", "config file, rewrite all other parameters if set")
} else {
flag.StringVar(&Conf.file, "f", ConfigDir+"/sower.toml", "config file, rewrite all other parameters if set")
flag.StringVar(&conf.file, "f", ConfigDir+"/sower.toml", "config file, rewrite all other parameters if set")
}

flag.StringVar(&installCmd, "install", "", "install service with cmd, eg: '-f \""+ConfigDir+"/sower.toml\"'")
flag.BoolVar(&uninstallFlag, "uninstall", false, "uninstall service")
}

func runAsService() {}
func afterInitFlag() {
switch {
case installCmd != "":
install()
case uninstallFlag:
uninstall()
default:
return
}
os.Exit(0)
}

func install() {
if err := ioutil.WriteFile(svcPath, []byte(fmt.Sprintf(svcFile, execFile, installCmd)), 0644); err != nil {
log.Fatalw("write service file", "err", err)
}

execute("launchctl unload " + svcPath)
if err := execute("launchctl load -w " + svcPath); err != nil {
if err := execute("launchctl load -wF " + svcPath); err != nil {
log.Fatalw("install service", "err", err)
}
}
Expand Down
25 changes: 20 additions & 5 deletions conf/conf_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ ExecStart=%s %s
RestartSec=3
Restart=on-failure`

var ConfigDir = ""
var (
ConfigDir = ""
installCmd = ""
uninstallFlag = false
)

func _init() {
func beforeInitFlag() {
if _, err := os.Stat(execDir + "/sower.toml"); err == nil {
ConfigDir = execDir

Expand All @@ -46,15 +50,26 @@ func _init() {
}

if _, err := os.Stat(ConfigDir + "/sower.toml"); err != nil {
flag.StringVar(&Conf.file, "f", "", "config file, rewrite all other parameters if set")
flag.StringVar(&conf.file, "f", "", "config file, rewrite all other parameters if set")
} else {
flag.StringVar(&Conf.file, "f", ConfigDir+"/sower.toml", "config file, rewrite all other parameters if set")
flag.StringVar(&conf.file, "f", ConfigDir+"/sower.toml", "config file, rewrite all other parameters if set")
}

flag.StringVar(&installCmd, "install", "", "install service with cmd, eg: '-f "+ConfigDir+"/sower.toml'")
flag.BoolVar(&uninstallFlag, "uninstall", false, "uninstall service")
}

func runAsService() {}
func afterInitFlag() {
switch {
case installCmd != "":
install()
case uninstallFlag:
uninstall()
default:
return
}
os.Exit(0)
}

func install() {
if err := ioutil.WriteFile(svcPath, []byte(fmt.Sprintf(svcFile, execFile, installCmd)), 0644); err != nil {
Expand Down
26 changes: 22 additions & 4 deletions conf/conf_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,28 @@ import (
const name = "sower"
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue

var ConfigDir = execDir
var (
ConfigDir = ""
installCmd = false
uninstallFlag = false
)

func beforeInitFlag() {
flag.StringVar(&conf.file, "f", filepath.Join(execDir, "sower.toml"), "config file, rewrite all other parameters if set")
flag.BoolVar(&installCmd, "install", false, "put any character to install as a service, eg: true")
}

func _init() {
flag.StringVar(&Conf.file, "f", filepath.Join(execDir, "sower.toml"), "config file, rewrite all other parameters if set")
flag.StringVar(&installCmd, "install", "", "put any character to install as a service, eg: true")
func afterInitFlag() {
switch {
case installCmd:
install()
case uninstallFlag:
uninstall()
default:
runAsService()
return
}
os.Exit(0)
}

func runAsService() {
Expand Down Expand Up @@ -86,6 +103,7 @@ func uninstall() {
return eventlog.Remove(name)
})
}

func serviceDo(fn func(*mgr.Service) error) {
mgrDo(func(m *mgr.Mgr) error {
s, err := m.OpenService(name)
Expand Down
3 changes: 1 addition & 2 deletions conf/sower.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ password="" # sower password
# eg: ":2222"="aa.bb.cc:22"

[client.router]
detect_level = 2 # 0~4, the bigger the harder to add
detect_timeout = "300ms"
detect_level = 1 # 0~4, the bigger the harder to add
direct_list = [
"**.in-addr.arpa",
"imap.*.*",
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion proxy/dhcp/dhcp_test.go → dhcp/dhcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dhcp_test
import (
"fmt"

"github.com/wweir/sower/proxy/dhcp"
"github.com/wweir/sower/dhcp"
)

func Example_dns() {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion proxy/dhcp/pick_iface_test.go → dhcp/pick_iface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package dhcp_test
import (
"fmt"

"github.com/wweir/sower/proxy/dhcp"
"github.com/wweir/sower/dhcp"
)

func Example_iface() {
Expand Down
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 396b08c

Please sign in to comment.