gost_software/cmd/gost/cfg.go
2018-11-29 22:09:10 +08:00

249 lines
4.4 KiB
Go

package main
import (
"bufio"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"io/ioutil"
"net/url"
"os"
"strings"
"time"
"github.com/ginuerzh/gost"
)
var (
routers []router
)
type baseConfig struct {
route
Routes []route
Debug bool
}
func parseBaseConfig(s string) (*baseConfig, error) {
file, err := os.Open(s)
if err != nil {
return nil, err
}
defer file.Close()
if err := json.NewDecoder(file).Decode(baseCfg); err != nil {
return nil, err
}
return baseCfg, nil
}
func (cfg *baseConfig) IsValid() bool {
return len(cfg.route.ServeNodes) > 0
}
var (
defaultCertFile = "cert.pem"
defaultKeyFile = "key.pem"
)
// Load the certificate from cert and key files, will use the default certificate if the provided info are invalid.
func tlsConfig(certFile, keyFile string) (*tls.Config, error) {
if certFile == "" {
certFile = defaultCertFile
}
if keyFile == "" {
keyFile = defaultKeyFile
}
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
return &tls.Config{Certificates: []tls.Certificate{cert}}, nil
}
func loadCA(caFile string) (cp *x509.CertPool, err error) {
if caFile == "" {
return
}
cp = x509.NewCertPool()
data, err := ioutil.ReadFile(caFile)
if err != nil {
return nil, err
}
if !cp.AppendCertsFromPEM(data) {
return nil, errors.New("AppendCertsFromPEM failed")
}
return
}
func parseKCPConfig(configFile string) (*gost.KCPConfig, error) {
if configFile == "" {
return nil, nil
}
file, err := os.Open(configFile)
if err != nil {
return nil, err
}
defer file.Close()
config := &gost.KCPConfig{}
if err = json.NewDecoder(file).Decode(config); err != nil {
return nil, err
}
return config, nil
}
func parseUsers(authFile string) (users []*url.Userinfo, err error) {
if authFile == "" {
return
}
file, err := os.Open(authFile)
if err != nil {
return
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
s := strings.SplitN(line, " ", 2)
if len(s) == 1 {
users = append(users, url.User(strings.TrimSpace(s[0])))
} else if len(s) == 2 {
users = append(users, url.UserPassword(strings.TrimSpace(s[0]), strings.TrimSpace(s[1])))
}
}
err = scanner.Err()
return
}
func parseIP(s string, port string) (ips []string) {
if s == "" {
return
}
if port == "" {
port = "8080" // default port
}
file, err := os.Open(s)
if err != nil {
ss := strings.Split(s, ",")
for _, s := range ss {
s = strings.TrimSpace(s)
if s != "" {
if !strings.Contains(s, ":") {
s = s + ":" + port
}
ips = append(ips, s)
}
}
return
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
if !strings.Contains(line, ":") {
line = line + ":" + port
}
ips = append(ips, line)
}
return
}
func parseBypass(s string) *gost.Bypass {
if s == "" {
return nil
}
var matchers []gost.Matcher
var reversed bool
if strings.HasPrefix(s, "~") {
reversed = true
s = strings.TrimLeft(s, "~")
}
f, err := os.Open(s)
if err != nil {
for _, s := range strings.Split(s, ",") {
s = strings.TrimSpace(s)
if s == "" {
continue
}
matchers = append(matchers, gost.NewMatcher(s))
}
return gost.NewBypass(reversed, matchers...)
}
defer f.Close()
bp := gost.NewBypass(reversed)
bp.Reload(f)
go gost.PeriodReload(bp, s)
return bp
}
func parseResolver(cfg string) gost.Resolver {
if cfg == "" {
return nil
}
timeout := 30 * time.Second
ttl := 60 * time.Second
var nss []gost.NameServer
f, err := os.Open(cfg)
if err != nil {
for _, s := range strings.Split(cfg, ",") {
s = strings.TrimSpace(s)
if s == "" {
continue
}
ss := strings.Split(s, "/")
if len(ss) == 1 {
nss = append(nss, gost.NameServer{
Addr: ss[0],
})
}
if len(ss) == 2 {
nss = append(nss, gost.NameServer{
Addr: ss[0],
Protocol: ss[1],
})
}
}
return gost.NewResolver(timeout, ttl, nss...)
}
defer f.Close()
resolver := gost.NewResolver(timeout, ttl)
resolver.Reload(f)
go gost.PeriodReload(resolver, cfg)
return resolver
}
func parseHosts(s string) *gost.Hosts {
f, err := os.Open(s)
if err != nil {
return nil
}
defer f.Close()
hosts := gost.NewHosts()
hosts.Reload(f)
go gost.PeriodReload(hosts, s)
return hosts
}