diff --git a/src/config.go b/src/config.go index 2e0acda..16491df 100644 --- a/src/config.go +++ b/src/config.go @@ -4,7 +4,6 @@ import ( log "github.com/sirupsen/logrus" "gopkg.in/yaml.v3" "net" - "strconv" "strings" ) @@ -38,53 +37,39 @@ type Config struct { } } -func isIP(ipAddr string, isRange bool, ipLength int, ipFlag string) bool { - var address string - if isRange { - temp := strings.Split(ipAddr, "/") - if len(temp) != 2 { // not {IP_ADDRESS}/{LENGTH} format - return false - } - length, err := strconv.Atoi(temp[1]) - if err != nil { // range length not a integer - return false - } - if length < 0 || length > ipLength { // length should between 0 ~ ipLength - return false - } - address = temp[0] - } else { - address = ipAddr +func isIP(ipAddr string, isCidr bool) bool { + if !isCidr { + return net.ParseIP(ipAddr) != nil } - ip := net.ParseIP(address) // try to convert ip - return ip != nil && strings.Contains(address, ipFlag) + _, _, err := net.ParseCIDR(ipAddr) + return err == nil } -func isIPv4(ipAddr string, isRange bool) bool { - return isIP(ipAddr, isRange, 32, ".") +func isIPv4(ipAddr string, isCidr bool) bool { + return isIP(ipAddr, isCidr) && strings.Contains(ipAddr, ".") } -func isIPv6(ipAddr string, isRange bool) bool { - return isIP(ipAddr, isRange, 128, ":") +func isIPv6(ipAddr string, isCidr bool) bool { + return isIP(ipAddr, isCidr) && strings.Contains(ipAddr, ":") } func loadConfig(rawConfig []byte) { config := Config{} - log.Debug("Decode yaml content -> \n", string(rawConfig)) + log.Debugf("Decode yaml content -> \n%s", string(rawConfig)) err := yaml.Unmarshal(rawConfig, &config) // yaml (or json) decode if err != nil { - panic(err) + log.Panicf("Decode config file error -> %v", err) } - log.Debug("Decoded config -> ", config) + log.Debugf("Decoded config -> %v", config) for _, address := range config.Network.DNS { // dns options if isIPv4(address, false) || isIPv6(address, false) { dnsServer = append(dnsServer, address) } else { - panic("Invalid DNS server -> " + address) + log.Panicf("Invalid DNS server -> %s", address) } } - log.Info("DNS server -> ", dnsServer) + log.Infof("DNS server -> %v", dnsServer) for _, address := range config.Network.ByPass { // bypass options if isIPv4(address, true) { @@ -92,29 +77,29 @@ func loadConfig(rawConfig []byte) { } else if isIPv6(address, true) { v6Bypass = append(v6Bypass, address) } else { - panic("Invalid bypass CIDR -> " + address) + log.Panicf("Invalid bypass CIDR -> %s", address) } } - log.Info("IPv4 bypass CIDR -> ", v4Bypass) - log.Info("IPv6 bypass CIDR -> ", v6Bypass) + log.Infof("IPv4 bypass CIDR -> %s", v4Bypass) + log.Infof("IPv6 bypass CIDR -> %s", v6Bypass) v4Address = config.Network.IPv4.Address v4Gateway = config.Network.IPv4.Gateway if v4Address != "" && !isIPv4(v4Address, true) { - panic("Invalid IPv4 address -> " + v4Address) + log.Panicf("Invalid IPv4 address -> %s", v4Address) } if v4Gateway != "" && !isIPv4(v4Gateway, false) { - panic("Invalid IPv4 gateway -> " + v4Gateway) + log.Panicf("Invalid IPv4 gateway -> %s", v4Gateway) } log.Infof("IPv4 -> address = %s | gateway = %s", v4Address, v4Gateway) v6Address = config.Network.IPv6.Address v6Gateway = config.Network.IPv6.Gateway if v6Address != "" && !isIPv6(v6Address, true) { - panic("Invalid IPv6 address -> " + v6Address) + log.Panicf("Invalid IPv6 address -> %s", v6Address) } if v6Gateway != "" && !isIPv6(v6Gateway, false) { - panic("Invalid IPv6 gateway -> " + v6Gateway) + log.Panicf("Invalid IPv6 gateway -> %s", v6Gateway) } log.Infof("IPv6 -> address = %s | gateway = %s", v6Address, v6Gateway) diff --git a/src/load.go b/src/load.go index 159d710..28fe3da 100644 --- a/src/load.go +++ b/src/load.go @@ -50,6 +50,10 @@ var outboundsConfig = `{ ] }` +type inboundsSettings struct { + Inbounds []interface{} `json:"inbounds"` +} + type sniffSettings struct { Enabled bool `json:"enabled"` RouteOnly bool `json:"routeOnly"` @@ -65,11 +69,7 @@ type inboundSettings struct { Sniffing sniffSettings `json:"sniffing"` } -type inboundsSettings struct { - Inbounds []interface{} `json:"inbounds"` -} - -func runCommand(command []string) (int, string) { +func runCommand(command ...string) (int, string) { log.Debugf("Running system command -> %v", command) process := exec.Command(command[0], command[1:]...) output, _ := process.CombinedOutput() @@ -93,8 +93,7 @@ func createFolder(folderPath string) { log.Debugf("Loading folder -> %s", folderPath) err := os.MkdirAll(folderPath, 0755) if err != nil { - log.Errorf("Failed to create folder -> %s", folderPath) - panic("Create folder failed") + log.Panicf("Failed to create folder -> %s", folderPath) } } @@ -102,8 +101,7 @@ func listFolder(folderPath string, suffix string) []string { var fileList []string files, err := ioutil.ReadDir(folderPath) if err != nil { - log.Errorf("Failed to list folder -> %s", folderPath) - panic("List folder failed") + log.Panicf("Failed to list folder -> %s", folderPath) } for _, file := range files { if strings.HasSuffix(file.Name(), suffix) { @@ -117,18 +115,15 @@ func copyFile(source string, target string) { log.Infof("Copy file `%s` => `%s`", source, target) srcFile, err := os.Open(source) if err != nil { - log.Errorf("Failed to open file -> %s", source) - panic("Open file failed") + log.Panicf("Failed to open file -> %s", source) } dstFile, err := os.OpenFile(target, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) if err != nil { - log.Errorf("Failed to open file -> %s", target) - panic("Open file failed") + log.Panicf("Failed to open file -> %s", target) } _, err = io.Copy(dstFile, srcFile) if err != nil { - log.Errorf("Failed to copy from `%s` to `%s`", source, target) - panic("Copy file failed") + log.Panicf("Failed to copy from `%s` to `%s`", source, target) } } @@ -141,8 +136,7 @@ func saveConfig(configDir string, caption string, content string, overwrite bool log.Debugf("Loading %s -> \n%s", filePath, content) err := os.WriteFile(filePath, []byte(content), 0644) if err != nil { - log.Errorf("File %s -> %v", caption, err) - panic("File save error") + log.Panicf("File %s -> %v", caption, err) } } @@ -210,24 +204,24 @@ func loadProxy(configDir string, exposeDir string) { logConfig = strings.ReplaceAll(logConfig, "${DIR}", exposeDir+"/log") saveConfig(configDir, "log", logConfig+"\n", true) - inboundsObject := inboundsSettings{} - sniffObject := sniffSettings{ + inbounds := inboundsSettings{} + sniff := sniffSettings{ Enabled: enableSniff, RouteOnly: !enableRedirect, DestOverride: []string{"http", "tls"}, } - inboundsObject.Inbounds = append(inboundsObject.Inbounds, loadTProxyConfig("tproxy", v4TProxyPort, sniffObject)) - inboundsObject.Inbounds = append(inboundsObject.Inbounds, loadTProxyConfig("tproxy6", v6TProxyPort, sniffObject)) + inbounds.Inbounds = append(inbounds.Inbounds, loadTProxyConfig("tproxy", v4TProxyPort, sniff)) + inbounds.Inbounds = append(inbounds.Inbounds, loadTProxyConfig("tproxy6", v6TProxyPort, sniff)) for tag, port := range httpInbounds { - inboundsObject.Inbounds = append(inboundsObject.Inbounds, loadHttpConfig(tag, port, sniffObject)) + inbounds.Inbounds = append(inbounds.Inbounds, loadHttpConfig(tag, port, sniff)) } for tag, port := range socksInbounds { - inboundsObject.Inbounds = append(inboundsObject.Inbounds, loadSocksConfig(tag, port, sniffObject)) + inbounds.Inbounds = append(inbounds.Inbounds, loadSocksConfig(tag, port, sniff)) } for _, addon := range addOnInbounds { - inboundsObject.Inbounds = append(inboundsObject.Inbounds, addon) + inbounds.Inbounds = append(inbounds.Inbounds, addon) } - inboundsConfig, _ := json.MarshalIndent(inboundsObject, "", " ") // json encode + inboundsConfig, _ := json.MarshalIndent(inbounds, "", " ") // json encode saveConfig(configDir, "inbounds", string(inboundsConfig)+"\n", true) for _, configFile := range listFolder(exposeDir+"/config", ".json") { diff --git a/src/network.go b/src/network.go index 029fcbd..c719d99 100644 --- a/src/network.go +++ b/src/network.go @@ -19,46 +19,45 @@ func loadDns() { } err := os.WriteFile("/etc/resolv.conf", []byte(dnsContent), 0644) if err != nil { - log.Error("Setting up DNS failed") - panic("Setting up DNS failed") + log.Panic("Setting up DNS failed") } } func loadNetwork() { log.Info("Enabled IP forward") - runCommand([]string{"sysctl", "-w", "net.ipv4.ip_forward=1"}) - runCommand([]string{"sysctl", "-w", "net.ipv6.conf.all.forwarding=1"}) + runCommand("sysctl", "-w", "net.ipv4.ip_forward=1") + runCommand("sysctl", "-w", "net.ipv6.conf.all.forwarding=1") log.Info("Flush system IP configure") - runCommand([]string{"ip", "link", "set", "eth0", "down"}) - runCommand([]string{"ip", "-4", "addr", "flush", "dev", "eth0"}) - runCommand([]string{"ip", "-6", "addr", "flush", "dev", "eth0"}) - runCommand([]string{"ip", "link", "set", "eth0", "down"}) + runCommand("ip", "link", "set", "eth0", "down") + runCommand("ip", "-4", "addr", "flush", "dev", "eth0") + runCommand("ip", "-6", "addr", "flush", "dev", "eth0") + runCommand("ip", "link", "set", "eth0", "down") log.Info("Setting up system IP configure") if v4Address != "" { - runCommand([]string{"ip", "-4", "addr", "add", v4Address, "dev", "eth0"}) + runCommand("ip", "-4", "addr", "add", v4Address, "dev", "eth0") } if v4Gateway != "" { - runCommand([]string{"ip", "-4", "route", "add", "default", "via", v4Gateway}) + runCommand("ip", "-4", "route", "add", "default", "via", v4Gateway) } if v6Address != "" { - runCommand([]string{"ip", "-6", "addr", "add", v6Address, "dev", "eth0"}) + runCommand("ip", "-6", "addr", "add", v6Address, "dev", "eth0") } if v6Gateway != "" { - runCommand([]string{"ip", "-6", "route", "add", "default", "via", v6Gateway}) + runCommand("ip", "-6", "route", "add", "default", "via", v6Gateway) } } func v4SysBypass() { - _, output := runCommand([]string{"ip", "-4", "addr"}) + _, output := runCommand("ip", "-4", "addr") for _, temp := range regexp.MustCompile(`inet (\S+)`).FindAllStringSubmatch(output, -1) { v4Bypass = append(v4Bypass, temp[1]) } } func v6SysBypass() { - _, output := runCommand([]string{"ip", "-6", "addr"}) + _, output := runCommand("ip", "-6", "addr") for _, temp := range regexp.MustCompile(`inet6 (\S+)`).FindAllStringSubmatch(output, -1) { v6Bypass = append(v6Bypass, temp[1]) } @@ -67,33 +66,33 @@ func v6SysBypass() { func loadTProxy() { log.Info("Setting up TProxy of IPv4") v4TableNum := strconv.Itoa(v4RouteTable) - runCommand([]string{"ip", "-4", "rule", "add", "fwmark", "1", "table", v4TableNum}) - runCommand([]string{"ip", "-4", "route", "add", "local", "0.0.0.0/0", "dev", "lo", "table", v4TableNum}) - runCommand([]string{"iptables", "-t", "mangle", "-N", "XPROXY"}) + runCommand("ip", "-4", "rule", "add", "fwmark", "1", "table", v4TableNum) + runCommand("ip", "-4", "route", "add", "local", "0.0.0.0/0", "dev", "lo", "table", v4TableNum) + runCommand("iptables", "-t", "mangle", "-N", "XPROXY") v4SysBypass() log.Infof("Setting up IPv4 bypass CIDR -> %v", v4Bypass) for _, cidr := range v4Bypass { - runCommand([]string{"iptables", "-t", "mangle", "-A", "XPROXY", "-d", cidr, "-j", "RETURN"}) + runCommand("iptables", "-t", "mangle", "-A", "XPROXY", "-d", cidr, "-j", "RETURN") } - runCommand([]string{"iptables", "-t", "mangle", "-A", "XPROXY", "-p", "tcp", "-j", "TPROXY", - "--on-port", strconv.Itoa(v4TProxyPort), "--tproxy-mark", "1"}) - runCommand([]string{"iptables", "-t", "mangle", "-A", "XPROXY", "-p", "udp", "-j", "TPROXY", - "--on-port", strconv.Itoa(v4TProxyPort), "--tproxy-mark", "1"}) - runCommand([]string{"iptables", "-t", "mangle", "-A", "PREROUTING", "-j", "XPROXY"}) + runCommand("iptables", "-t", "mangle", "-A", "XPROXY", "-p", "tcp", "-j", "TPROXY", + "--on-port", strconv.Itoa(v4TProxyPort), "--tproxy-mark", "1") + runCommand("iptables", "-t", "mangle", "-A", "XPROXY", "-p", "udp", "-j", "TPROXY", + "--on-port", strconv.Itoa(v4TProxyPort), "--tproxy-mark", "1") + runCommand("iptables", "-t", "mangle", "-A", "PREROUTING", "-j", "XPROXY") log.Info("Setting up TProxy of IPv6") v6TableNum := strconv.Itoa(v6RouteTable) - runCommand([]string{"ip", "-6", "rule", "add", "fwmark", "1", "table", v6TableNum}) - runCommand([]string{"ip", "-6", "route", "add", "local", "::/0", "dev", "lo", "table", v6TableNum}) - runCommand([]string{"ip6tables", "-t", "mangle", "-N", "XPROXY6"}) + runCommand("ip", "-6", "rule", "add", "fwmark", "1", "table", v6TableNum) + runCommand("ip", "-6", "route", "add", "local", "::/0", "dev", "lo", "table", v6TableNum) + runCommand("ip6tables", "-t", "mangle", "-N", "XPROXY6") v6SysBypass() log.Infof("Setting up IPv6 bypass CIDR -> %v", v6Bypass) for _, cidr := range v6Bypass { - runCommand([]string{"ip6tables", "-t", "mangle", "-A", "XPROXY6", "-d", cidr, "-j", "RETURN"}) + runCommand("ip6tables", "-t", "mangle", "-A", "XPROXY6", "-d", cidr, "-j", "RETURN") } - runCommand([]string{"ip6tables", "-t", "mangle", "-A", "XPROXY6", "-p", "tcp", "-j", "TPROXY", - "--on-port", strconv.Itoa(v6TProxyPort), "--tproxy-mark", "1"}) - runCommand([]string{"ip6tables", "-t", "mangle", "-A", "XPROXY6", "-p", "udp", "-j", "TPROXY", - "--on-port", strconv.Itoa(v6TProxyPort), "--tproxy-mark", "1"}) - runCommand([]string{"ip6tables", "-t", "mangle", "-A", "PREROUTING", "-j", "XPROXY6"}) + runCommand("ip6tables", "-t", "mangle", "-A", "XPROXY6", "-p", "tcp", "-j", "TPROXY", + "--on-port", strconv.Itoa(v6TProxyPort), "--tproxy-mark", "1") + runCommand("ip6tables", "-t", "mangle", "-A", "XPROXY6", "-p", "udp", "-j", "TPROXY", + "--on-port", strconv.Itoa(v6TProxyPort), "--tproxy-mark", "1") + runCommand("ip6tables", "-t", "mangle", "-A", "PREROUTING", "-j", "XPROXY6") }