Browse Source

refactor: split into multi packages

v1.x.x
dnomd343 2 years ago
parent
commit
eeb6a34b03
  1. 25
      cmd/asset/geofile.go
  2. 15
      cmd/asset/update.go
  3. 94
      cmd/common/file.go
  4. 22
      cmd/common/net.go
  5. 19
      cmd/common/sys.go
  6. 19
      cmd/network/dns.go
  7. 18
      cmd/network/main.go
  8. 51
      cmd/network/network.go
  9. 47
      cmd/network/tproxy.go
  10. 84
      cmd/proxy/config.go
  11. 65
      cmd/proxy/load.go
  12. 37
      cmd/proxy/object.go
  13. 19
      main.go
  14. 18
      src/config.go
  15. 286
      src/load.go
  16. 98
      src/network.go

25
cmd/asset/geofile.go

@ -0,0 +1,25 @@
package asset
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
)
func extractGeoFile(archivePath string, geoFile string, targetDir string) {
if common.IsFileExist(targetDir + "/" + geoFile) {
log.Debugf("Asset %s exist -> skip extract", geoFile)
return
}
log.Infof("Extract asset file -> %s", targetDir+"/"+geoFile)
common.RunCommand("tar", "xvf", archivePath, "./"+geoFile, "-C", targetDir)
}
func LoadGeoIp(assetFile string, assetDir string) {
common.CreateFolder(assetDir)
extractGeoFile(assetFile, "geoip.dat", assetDir)
}
func LoadGeoSite(assetFile string, assetDir string) {
common.CreateFolder(assetDir)
extractGeoFile(assetFile, "geosite.dat", assetDir)
}

15
cmd/asset/update.go

@ -0,0 +1,15 @@
package asset
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
)
func UpdateAssets(urls map[string]string, assetDir string) {
if len(urls) != 0 {
log.Info("Start update assets")
for file, url := range urls {
common.DownloadFile(url, assetDir+"/"+file)
}
}
}

94
cmd/common/file.go

@ -0,0 +1,94 @@
package common
import (
log "github.com/sirupsen/logrus"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
)
func CreateFolder(folderPath string) {
log.Debugf("Create folder -> %s", folderPath)
err := os.MkdirAll(folderPath, 0755)
if err != nil {
log.Panicf("Failed to create folder -> %s", folderPath)
}
}
func IsFileExist(filePath string) bool {
s, err := os.Stat(filePath)
if err != nil { // file or folder not exist
return false
}
return !s.IsDir()
}
func WriteFile(filePath string, content string, overwrite bool) {
if !overwrite && IsFileExist(filePath) { // file exist and don't overwrite
log.Debugf("File `%s` exist -> skip write", filePath)
return
}
log.Debugf("Write file `%s` -> \n%s", filePath, content)
err := os.WriteFile(filePath, []byte(content), 0644)
if err != nil {
log.Panicf("Failed to write `%s` -> %v", filePath, err)
}
}
func ListFiles(folderPath string, suffix string) []string {
var fileList []string
files, err := ioutil.ReadDir(folderPath)
if err != nil {
log.Panicf("Failed to list folder -> %s", folderPath)
}
for _, file := range files {
if strings.HasSuffix(file.Name(), suffix) {
fileList = append(fileList, file.Name())
}
}
return fileList
}
func CopyFile(source string, target string) {
log.Infof("Copy file `%s` => `%s`", source, target)
if IsFileExist(target) {
log.Warningf("File `%s` will be overrided", target)
}
srcFile, err := os.Open(source)
if err != nil {
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 {
_ = srcFile.Close()
log.Panicf("Failed to open file -> %s", target)
}
_, err = io.Copy(dstFile, srcFile)
_ = srcFile.Close()
_ = dstFile.Close()
if err != nil {
log.Panicf("Failed to copy from `%s` to `%s`", source, target)
}
}
func DownloadFile(url string, file string) {
log.Debugf("File download `%s` => `%s`", url, file)
resp, err := http.Get(url)
if err != nil {
log.Errorf("Download `%s` error -> %v", url, err)
return
}
out, err := os.OpenFile(file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
_ = resp.Body.Close()
log.Panicf("Open `%s` error -> %v", file, err)
}
_, err = io.Copy(out, resp.Body)
_ = resp.Body.Close()
if err != nil {
log.Panicf("File `%s` save error -> %v", file, err)
}
log.Infof("Download success `%s` => `%s`", url, file)
}

22
cmd/common/net.go

@ -0,0 +1,22 @@
package common
import (
"net"
"strings"
)
func isIP(ipAddr string, isCidr bool) bool {
if !isCidr {
return net.ParseIP(ipAddr) != nil
}
_, _, err := net.ParseCIDR(ipAddr)
return err == nil
}
func IsIPv4(ipAddr string, isCidr bool) bool {
return isIP(ipAddr, isCidr) && strings.Contains(ipAddr, ".")
}
func IsIPv6(ipAddr string, isCidr bool) bool {
return isIP(ipAddr, isCidr) && strings.Contains(ipAddr, ":")
}

19
cmd/common/sys.go

@ -0,0 +1,19 @@
package common
import (
log "github.com/sirupsen/logrus"
"os/exec"
"syscall"
)
func RunCommand(command ...string) (int, string) {
log.Debugf("Running system command -> %v", command)
process := exec.Command(command[0], command[1:]...)
output, _ := process.CombinedOutput()
log.Debugf("Command %v -> \n%s", command, string(output))
code := process.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
if code != 0 {
log.Warningf("Command %v return code %d", command, code)
}
return code, string(output)
}

19
cmd/network/dns.go

@ -0,0 +1,19 @@
package network
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
)
func loadDns(dnsServer []string) {
if len(dnsServer) == 0 {
log.Info("Using system DNS server")
return
}
log.Infof("Setting up DNS server -> %v", dnsServer)
dnsConfig := ""
for _, address := range dnsServer {
dnsConfig += "nameserver " + address + "\n"
}
common.WriteFile("/etc/resolv.conf", dnsConfig, true)
}

18
cmd/network/main.go

@ -0,0 +1,18 @@
package network
type Config struct {
IPv4 struct {
Address string
Gateway string
RouteTable int
TProxyPort int
}
V4RouteTable int
V6RouteTable int
V4TProxyPort int
V6TProxyPort int
}
func Load() {
}

51
cmd/network/network.go

@ -0,0 +1,51 @@
package network
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
"regexp"
)
func getV4Cidr() []string {
var v4Cidr []string
_, output := common.RunCommand("ip", "-4", "addr")
for _, temp := range regexp.MustCompile(`inet (\S+)`).FindAllStringSubmatch(output, -1) {
v4Cidr = append(v4Cidr, temp[1])
}
return v4Cidr
}
func getV6Cidr() []string {
var v6Cidr []string
_, output := common.RunCommand("ip", "-6", "addr")
for _, temp := range regexp.MustCompile(`inet6 (\S+)`).FindAllStringSubmatch(output, -1) {
v6Cidr = append(v6Cidr, temp[1])
}
return v6Cidr
}
func loadNetwork(v4Address string, v4Gateway string, v6Address string, v6Gateway string) {
log.Info("Enabled IP forward")
common.RunCommand("sysctl", "-w", "net.ipv4.ip_forward=1")
common.RunCommand("sysctl", "-w", "net.ipv6.conf.all.forwarding=1")
log.Info("Flush system IP configure")
common.RunCommand("ip", "link", "set", "eth0", "down")
common.RunCommand("ip", "-4", "addr", "flush", "dev", "eth0")
common.RunCommand("ip", "-6", "addr", "flush", "dev", "eth0")
common.RunCommand("ip", "link", "set", "eth0", "down")
log.Info("Setting up system IP configure")
if v4Address != "" {
common.RunCommand("ip", "-4", "addr", "add", v4Address, "dev", "eth0")
}
if v4Gateway != "" {
common.RunCommand("ip", "-4", "route", "add", "default", "via", v4Gateway)
}
if v6Address != "" {
common.RunCommand("ip", "-6", "addr", "add", v6Address, "dev", "eth0")
}
if v6Gateway != "" {
common.RunCommand("ip", "-6", "route", "add", "default", "via", v6Gateway)
}
}

47
cmd/network/tproxy.go

@ -0,0 +1,47 @@
package network
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
"strconv"
)
type tproxyConfig struct {
routeTable int
tproxyPort int
bypassCidr []string
}
func loadV4TProxy(config tproxyConfig) {
log.Info("Setting up TProxy of IPv4")
tableNum := strconv.Itoa(config.routeTable)
common.RunCommand("ip", "-4", "rule", "add", "fwmark", "1", "table", tableNum)
common.RunCommand("ip", "-4", "route", "add", "local", "0.0.0.0/0", "dev", "lo", "table", tableNum)
common.RunCommand("iptables", "-t", "mangle", "-N", "XPROXY")
log.Infof("Setting up IPv4 bypass CIDR -> %v", config.bypassCidr)
for _, cidr := range config.bypassCidr {
common.RunCommand("iptables", "-t", "mangle", "-A", "XPROXY", "-d", cidr, "-j", "RETURN")
}
common.RunCommand("iptables", "-t", "mangle", "-A", "XPROXY",
"-p", "tcp", "-j", "TPROXY", "--on-port", strconv.Itoa(config.tproxyPort), "--tproxy-mark", "1")
common.RunCommand("iptables", "-t", "mangle", "-A", "XPROXY",
"-p", "udp", "-j", "TPROXY", "--on-port", strconv.Itoa(config.tproxyPort), "--tproxy-mark", "1")
common.RunCommand("iptables", "-t", "mangle", "-A", "PREROUTING", "-j", "XPROXY")
}
func loadV6TProxy(config tproxyConfig) {
log.Info("Setting up TProxy of IPv6")
tableNum := strconv.Itoa(config.routeTable)
common.RunCommand("ip", "-6", "rule", "add", "fwmark", "1", "table", tableNum)
common.RunCommand("ip", "-6", "route", "add", "local", "::/0", "dev", "lo", "table", tableNum)
common.RunCommand("ip6tables", "-t", "mangle", "-N", "XPROXY6")
log.Infof("Setting up IPv6 bypass CIDR -> %v", config.bypassCidr)
for _, cidr := range config.bypassCidr {
common.RunCommand("ip6tables", "-t", "mangle", "-A", "XPROXY6", "-d", cidr, "-j", "RETURN")
}
common.RunCommand("ip6tables", "-t", "mangle", "-A", "XPROXY6",
"-p", "tcp", "-j", "TPROXY", "--on-port", strconv.Itoa(config.tproxyPort), "--tproxy-mark", "1")
common.RunCommand("ip6tables", "-t", "mangle", "-A", "XPROXY6",
"-p", "udp", "-j", "TPROXY", "--on-port", strconv.Itoa(config.tproxyPort), "--tproxy-mark", "1")
common.RunCommand("ip6tables", "-t", "mangle", "-A", "PREROUTING", "-j", "XPROXY6")
}

84
cmd/proxy/config.go

@ -0,0 +1,84 @@
package proxy
var dnsConfig = `{
"dns": {
"servers": [
"localhost"
]
}
}`
var routeConfig = `{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "node"
}
]
}
}`
var outboundsConfig = `{
"outbounds": [
{
"tag": "node",
"protocol": "freedom",
"settings": {}
}
]
}`
func httpConfig(tag string, port int, sniff sniffObject) interface{} {
type empty struct{}
return inboundObject{
Tag: tag,
Port: port,
Protocol: "http",
Settings: empty{},
StreamSettings: empty{},
Sniffing: sniff,
}
}
func socksConfig(tag string, port int, sniff sniffObject) interface{} {
type empty struct{}
type socksObject struct {
UDP bool `json:"udp"`
}
return inboundObject{
Tag: tag,
Port: port,
Protocol: "socks",
Settings: socksObject{UDP: true},
StreamSettings: empty{},
Sniffing: sniff,
}
}
func tproxyConfig(tag string, port int, sniff sniffObject) interface{} {
type tproxyObject struct {
Network string `json:"network"`
FollowRedirect bool `json:"followRedirect"`
}
type tproxyStreamObject struct {
Sockopt struct {
Tproxy string `json:"tproxy"`
} `json:"sockopt"`
}
tproxyStream := tproxyStreamObject{}
tproxyStream.Sockopt.Tproxy = "tproxy"
return inboundObject{
Tag: tag,
Port: port,
Protocol: "dokodemo-door",
Settings: tproxyObject{
Network: "tcp,udp",
FollowRedirect: true,
},
StreamSettings: tproxyStream,
Sniffing: sniff,
}
}

65
cmd/proxy/load.go

@ -0,0 +1,65 @@
package proxy
import (
"XProxy/cmd/common"
"encoding/json"
log "github.com/sirupsen/logrus"
)
func saveConfig(configDir string, caption string, content string, overwrite bool) {
filePath := configDir + "/" + caption + ".json"
common.WriteFile(filePath, content+"\n", overwrite)
}
func jsonEncode(raw interface{}) string {
jsonOutput, _ := json.MarshalIndent(raw, "", " ") // json encode
return string(jsonOutput)
}
func loadLog(logLevel string, logDir string) string {
if logLevel != "debug" && logLevel != "info" &&
logLevel != "warning" && logLevel != "error" && logLevel != "none" {
log.Warningf("Unknown log level -> %s", logLevel)
logLevel = "warning" // using `warning` as default
}
return jsonEncode(logObject{
Loglevel: logLevel,
Access: logDir + "/access.log",
Error: logDir + "/error.log",
})
}
func loadInbounds(config Config) string {
inbounds := inboundsObject{}
sniff := sniffObject{
Enabled: config.Sniff,
RouteOnly: !config.Redirect,
DestOverride: []string{"http", "tls"},
}
inbounds.Inbounds = append(inbounds.Inbounds, tproxyConfig("tproxy", config.V4TProxyPort, sniff))
inbounds.Inbounds = append(inbounds.Inbounds, tproxyConfig("tproxy6", config.V6TProxyPort, sniff))
for tag, port := range config.HttpInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, httpConfig(tag, port, sniff))
}
for tag, port := range config.SocksInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, socksConfig(tag, port, sniff))
}
for _, addon := range config.AddOnInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, addon)
}
return jsonEncode(inbounds)
}
func Load(configDir string, exposeDir string, config Config) {
common.CreateFolder(exposeDir + "/log")
common.CreateFolder(exposeDir + "/config")
common.CreateFolder(configDir)
saveConfig(exposeDir+"/config", "dns", dnsConfig, false)
saveConfig(exposeDir+"/config", "route", routeConfig, false)
saveConfig(exposeDir+"/config", "outbounds", outboundsConfig, false)
saveConfig(configDir, "inbounds", loadInbounds(config), true)
saveConfig(configDir, "log", loadLog(config.LogLevel, exposeDir+"/log"), true)
for _, configFile := range common.ListFiles(exposeDir+"/config", ".json") {
common.CopyFile(exposeDir+"/config/"+configFile, configDir+"/"+configFile)
}
}

37
cmd/proxy/object.go

@ -0,0 +1,37 @@
package proxy
type Config struct {
Sniff bool
Redirect bool
V4TProxyPort int
V6TProxyPort int
LogLevel string
HttpInbounds map[string]int
SocksInbounds map[string]int
AddOnInbounds []interface{}
}
type logObject struct {
Loglevel string `json:"loglevel"`
Access string `json:"access"`
Error string `json:"error"`
}
type inboundsObject struct {
Inbounds []interface{} `json:"inbounds"`
}
type sniffObject struct {
Enabled bool `json:"enabled"`
RouteOnly bool `json:"routeOnly"`
DestOverride []string `json:"destOverride"`
}
type inboundObject struct {
Tag string `json:"tag"`
Port int `json:"port"`
Protocol string `json:"protocol"`
Settings interface{} `json:"settings"`
StreamSettings interface{} `json:"streamSettings"`
Sniffing sniffObject `json:"sniffing"`
}

19
main.go

@ -0,0 +1,19 @@
package main
import (
"XProxy/cmd/network"
"fmt"
log "github.com/sirupsen/logrus"
)
func main() {
log.SetLevel(log.DebugLevel)
fmt.Println("xproxy start")
//common.CreateFolder("/tmp/test")
//fmt.Println(common.IsFileExist("/tmp/1.jpg"))
//fmt.Println(common.ListFiles("/xproxy/config", ".json"))
net = network.Config{
V4RouteTable: 12,
}
}

18
src/config.go

@ -3,9 +3,7 @@ package main
import ( import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"net"
"os" "os"
"strings"
) )
var v4Bypass []string var v4Bypass []string
@ -66,22 +64,6 @@ type Config struct {
} `yaml:"network"` } `yaml:"network"`
} }
func isIP(ipAddr string, isCidr bool) bool {
if !isCidr {
return net.ParseIP(ipAddr) != nil
}
_, _, err := net.ParseCIDR(ipAddr)
return err == nil
}
func isIPv4(ipAddr string, isCidr bool) bool {
return isIP(ipAddr, isCidr) && strings.Contains(ipAddr, ".")
}
func isIPv6(ipAddr string, isCidr bool) bool {
return isIP(ipAddr, isCidr) && strings.Contains(ipAddr, ":")
}
func loadConfig(configFile string) { func loadConfig(configFile string) {
if !isFileExist(configFile) { // load default configure if !isFileExist(configFile) { // load default configure
log.Infof("Load default configure -> %s", configFile) log.Infof("Load default configure -> %s", configFile)

286
src/load.go

@ -1,286 +0,0 @@
package main
import (
"encoding/json"
log "github.com/sirupsen/logrus"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
"syscall"
)
var logConfig = `{
"log": {
"loglevel": "${LEVEL}",
"access": "${DIR}/access.log",
"error": "${DIR}/error.log"
}
}`
var dnsConfig = `{
"dns": {
"servers": [
"localhost"
]
}
}`
var routeConfig = `{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "node"
}
]
}
}`
var outboundsConfig = `{
"outbounds": [
{
"tag": "node",
"protocol": "freedom",
"settings": {}
}
]
}`
type inboundsSettings struct {
Inbounds []interface{} `json:"inbounds"`
}
type sniffSettings struct {
Enabled bool `json:"enabled"`
RouteOnly bool `json:"routeOnly"`
DestOverride []string `json:"destOverride"`
}
type inboundSettings struct {
Tag string `json:"tag"`
Port int `json:"port"`
Protocol string `json:"protocol"`
Settings interface{} `json:"settings"`
StreamSettings interface{} `json:"streamSettings"`
Sniffing sniffSettings `json:"sniffing"`
}
func runCommand(command ...string) (int, string) {
log.Debugf("Running system command -> %v", command)
process := exec.Command(command[0], command[1:]...)
output, _ := process.CombinedOutput()
log.Debugf("Command %v -> \n%s", command, string(output))
code := process.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
if code != 0 {
log.Warningf("Command %v return code %d", command, code)
}
return code, string(output)
}
func isFileExist(filePath string) bool {
s, err := os.Stat(filePath)
if err != nil { // file or folder not exist
return false
}
return !s.IsDir()
}
func createFolder(folderPath string) {
log.Debugf("Create folder -> %s", folderPath)
err := os.MkdirAll(folderPath, 0755)
if err != nil {
log.Panicf("Failed to create folder -> %s", folderPath)
}
}
func listFolder(folderPath string, suffix string) []string {
var fileList []string
files, err := ioutil.ReadDir(folderPath)
if err != nil {
log.Panicf("Failed to list folder -> %s", folderPath)
}
for _, file := range files {
if strings.HasSuffix(file.Name(), suffix) {
fileList = append(fileList, file.Name())
}
}
return fileList
}
func copyFile(source string, target string) {
log.Infof("Copy file `%s` => `%s`", source, target)
srcFile, err := os.Open(source)
if err != nil {
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.Panicf("Failed to open file -> %s", target)
}
_, err = io.Copy(dstFile, srcFile)
if err != nil {
log.Panicf("Failed to copy from `%s` to `%s`", source, target)
}
}
func downloadFile(url string, file string) bool {
log.Debugf("File download %s => %s", url, file)
resp, err := http.Get(url)
if err != nil {
log.Errorf("Download %s error -> %v", url, err)
return false
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
out, err := os.OpenFile(file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
_ = resp.Body.Close()
log.Panicf("Open %s error -> %v", file, err)
}
_, err = io.Copy(out, resp.Body)
_ = resp.Body.Close()
if err != nil {
log.Panicf("File %s save error -> %v", file, err)
}
log.Infof("Download success `%s` => `%s`", url, file)
return true
}
func saveConfig(configDir string, caption string, content string, overwrite bool) {
filePath := configDir + "/" + caption + ".json"
if !overwrite && isFileExist(filePath) { // file exist and don't overwrite
log.Debugf("Skip loading config -> %s", filePath)
return
}
log.Debugf("Loading %s -> \n%s", filePath, content)
err := os.WriteFile(filePath, []byte(content), 0644)
if err != nil {
log.Panicf("File %s -> %v", caption, err)
}
}
func loadHttpConfig(tag string, port int, sniffObject sniffSettings) interface{} {
type empty struct{}
return inboundSettings{
Tag: tag,
Port: port,
Protocol: "http",
Settings: empty{},
StreamSettings: empty{},
Sniffing: sniffObject,
}
}
func loadSocksConfig(tag string, port int, sniffObject sniffSettings) interface{} {
type empty struct{}
type socksSettings struct {
UDP bool `json:"udp"`
}
return inboundSettings{
Tag: tag,
Port: port,
Protocol: "socks",
Settings: socksSettings{UDP: true},
StreamSettings: empty{},
Sniffing: sniffObject,
}
}
func loadTProxyConfig(tag string, port int, sniffObject sniffSettings) interface{} {
type tproxySettings struct {
Network string `json:"network"`
FollowRedirect bool `json:"followRedirect"`
}
type tproxyStreamSettings struct {
Sockopt struct {
Tproxy string `json:"tproxy"`
} `json:"sockopt"`
}
tproxyStream := tproxyStreamSettings{}
tproxyStream.Sockopt.Tproxy = "tproxy"
return inboundSettings{
Tag: tag,
Port: port,
Protocol: "dokodemo-door",
Settings: tproxySettings{
Network: "tcp,udp",
FollowRedirect: true,
},
StreamSettings: tproxyStream,
Sniffing: sniffObject,
}
}
func loadProxy(configDir string, exposeDir string) {
createFolder(exposeDir + "/log")
createFolder(exposeDir + "/config")
createFolder(configDir)
saveConfig(exposeDir+"/config", "dns", dnsConfig+"\n", false)
saveConfig(exposeDir+"/config", "route", routeConfig+"\n", false)
saveConfig(exposeDir+"/config", "outbounds", outboundsConfig+"\n", false)
logConfig = strings.ReplaceAll(logConfig, "${LEVEL}", logLevel)
logConfig = strings.ReplaceAll(logConfig, "${DIR}", exposeDir+"/log")
saveConfig(configDir, "log", logConfig+"\n", true)
inbounds := inboundsSettings{}
sniff := sniffSettings{
Enabled: enableSniff,
RouteOnly: !enableRedirect,
DestOverride: []string{"http", "tls"},
}
inbounds.Inbounds = append(inbounds.Inbounds, loadTProxyConfig("tproxy", v4TProxyPort, sniff))
inbounds.Inbounds = append(inbounds.Inbounds, loadTProxyConfig("tproxy6", v6TProxyPort, sniff))
for tag, port := range httpInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, loadHttpConfig(tag, port, sniff))
}
for tag, port := range socksInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, loadSocksConfig(tag, port, sniff))
}
for _, addon := range addOnInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, addon)
}
inboundsConfig, _ := json.MarshalIndent(inbounds, "", " ") // json encode
saveConfig(configDir, "inbounds", string(inboundsConfig)+"\n", true)
for _, configFile := range listFolder(exposeDir+"/config", ".json") {
if configFile == "log.json" || configFile == "inbounds.json" {
log.Warningf("Config file `%s` will be overrided", configFile)
}
copyFile(exposeDir+"/config/"+configFile, configDir+"/"+configFile)
}
}
func extractGeoFile(archivePath string, geoFile string, targetDir string) {
if isFileExist(targetDir + "/" + geoFile) {
log.Debugf("Asset %s exist -> skip extract", geoFile)
return
}
log.Infof("Extract asset file -> %s", targetDir+"/"+geoFile)
runCommand("tar", "xvf", archivePath, "./"+geoFile, "-C", targetDir)
}
func loadGeoIp(assetDir string) {
createFolder(assetDir)
extractGeoFile(assetFile, "geoip.dat", assetDir)
}
func loadGeoSite(assetDir string) {
createFolder(assetDir)
extractGeoFile(assetFile, "geosite.dat", assetDir)
}
func updateAssets(assetDir string) {
if len(updateUrls) != 0 {
log.Info("Start update assets")
for file, url := range updateUrls {
downloadFile(url, assetDir+"/"+file)
}
}
}

98
src/network.go

@ -1,98 +0,0 @@
package main
import (
log "github.com/sirupsen/logrus"
"os"
"regexp"
"strconv"
)
func loadDns() {
if len(dnsServer) == 0 {
log.Info("Using system DNS server")
return
}
log.Infof("Setting up DNS server -> %v", dnsServer)
dnsContent := ""
for _, address := range dnsServer {
dnsContent += "nameserver " + address + "\n"
}
err := os.WriteFile("/etc/resolv.conf", []byte(dnsContent), 0644)
if err != nil {
log.Panic("Setting up DNS failed")
}
}
func loadNetwork() {
log.Info("Enabled IP forward")
runCommand("sysctl", "-w", "net.ipv4.ip_forward=1")
runCommand("sysctl", "-w", "net.ipv6.conf.all.forwarding=1")
log.Info("Flush system IP configure")
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("ip", "-4", "addr", "add", v4Address, "dev", "eth0")
}
if v4Gateway != "" {
runCommand("ip", "-4", "route", "add", "default", "via", v4Gateway)
}
if v6Address != "" {
runCommand("ip", "-6", "addr", "add", v6Address, "dev", "eth0")
}
if v6Gateway != "" {
runCommand("ip", "-6", "route", "add", "default", "via", v6Gateway)
}
}
func v4SysBypass() {
_, output := runCommand("ip", "-4", "addr")
for _, temp := range regexp.MustCompile(`inet (\S+)`).FindAllStringSubmatch(output, -1) {
v4Bypass = append(v4Bypass, temp[1])
}
}
func v6SysBypass() {
_, output := runCommand("ip", "-6", "addr")
for _, temp := range regexp.MustCompile(`inet6 (\S+)`).FindAllStringSubmatch(output, -1) {
v6Bypass = append(v6Bypass, temp[1])
}
}
func loadTProxy() {
log.Info("Setting up TProxy of IPv4")
v4TableNum := strconv.Itoa(v4RouteTable)
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("iptables", "-t", "mangle", "-A", "XPROXY", "-d", cidr, "-j", "RETURN")
}
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("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("ip6tables", "-t", "mangle", "-A", "XPROXY6", "-d", cidr, "-j", "RETURN")
}
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")
}
Loading…
Cancel
Save