Browse Source

update: complete proxy package

v1.x.x
dnomd343 2 years ago
parent
commit
2813bc8c3b
  1. 139
      cmd/common/file.go
  2. 43
      cmd/common/func.go
  3. 22
      cmd/common/net.go
  4. 19
      cmd/common/sys.go
  5. 135
      cmd/proxy/config.go
  6. 49
      cmd/proxy/main.go
  7. 37
      cmd/proxy/object.go
  8. 26
      main.go

139
cmd/common/file.go

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

43
cmd/common/func.go

@ -0,0 +1,43 @@
package common
import (
"encoding/json"
log "github.com/sirupsen/logrus"
"net"
"os/exec"
"strings"
"syscall"
)
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 JsonEncode(raw interface{}) string {
jsonOutput, _ := json.MarshalIndent(raw, "", " ") // json encode
return string(jsonOutput)
}
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)
}

22
cmd/common/net.go

@ -1,22 +0,0 @@
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

@ -1,19 +0,0 @@
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)
}

135
cmd/proxy/config.go

@ -1,5 +1,10 @@
package proxy package proxy
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
)
var dnsConfig = `{ var dnsConfig = `{
"dns": { "dns": {
"servers": [ "servers": [
@ -31,54 +36,92 @@ var outboundsConfig = `{
] ]
}` }`
func httpConfig(tag string, port int, sniff sniffObject) interface{} { type logObject struct {
type empty struct{} Loglevel string `json:"loglevel"`
return inboundObject{ Access string `json:"access"`
Tag: tag, Error string `json:"error"`
Port: port, }
Protocol: "http",
Settings: empty{}, type inboundsObject struct {
StreamSettings: empty{}, Inbounds []interface{} `json:"inbounds"`
Sniffing: sniff, }
}
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"`
}
func loadLogConfig(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 common.JsonEncode(logObject{
Loglevel: logLevel,
Access: logDir + "/access.log",
Error: logDir + "/error.log",
})
} }
func socksConfig(tag string, port int, sniff sniffObject) interface{} { func loadHttpConfig(tag string, port int, sniff sniffObject) interface{} {
type empty struct{} type empty struct{}
type socksObject struct { return inboundObject{
UDP bool `json:"udp"` Tag: tag,
} Port: port,
return inboundObject{ Protocol: "http",
Tag: tag, Settings: empty{},
Port: port, StreamSettings: empty{},
Protocol: "socks", Sniffing: sniff,
Settings: socksObject{UDP: true}, }
StreamSettings: empty{},
Sniffing: sniff,
}
} }
func tproxyConfig(tag string, port int, sniff sniffObject) interface{} { func loadSocksConfig(tag string, port int, sniff sniffObject) interface{} {
type tproxyObject struct { type empty struct{}
Network string `json:"network"` type socksObject struct {
FollowRedirect bool `json:"followRedirect"` UDP bool `json:"udp"`
} }
type tproxyStreamObject struct { return inboundObject{
Sockopt struct { Tag: tag,
Tproxy string `json:"tproxy"` Port: port,
} `json:"sockopt"` Protocol: "socks",
} Settings: socksObject{UDP: true},
tproxyStream := tproxyStreamObject{} StreamSettings: empty{},
tproxyStream.Sockopt.Tproxy = "tproxy" Sniffing: sniff,
return inboundObject{ }
Tag: tag, }
Port: port,
Protocol: "dokodemo-door", func loadTProxyConfig(tag string, port int, sniff sniffObject) interface{} {
Settings: tproxyObject{ type tproxyObject struct {
Network: "tcp,udp", Network string `json:"network"`
FollowRedirect: true, FollowRedirect bool `json:"followRedirect"`
}, }
StreamSettings: tproxyStream, type tproxyStreamObject struct {
Sniffing: sniff, 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,
}
} }

49
cmd/proxy/load.go → cmd/proxy/main.go

@ -2,52 +2,45 @@ package proxy
import ( import (
"XProxy/cmd/common" "XProxy/cmd/common"
"encoding/json"
log "github.com/sirupsen/logrus"
) )
type Config struct {
Sniff bool
Redirect bool
V4TProxyPort int
V6TProxyPort int
LogLevel string
HttpInbounds map[string]int
SocksInbounds map[string]int
AddOnInbounds []interface{}
}
func saveConfig(configDir string, caption string, content string, overwrite bool) { func saveConfig(configDir string, caption string, content string, overwrite bool) {
filePath := configDir + "/" + caption + ".json" filePath := configDir + "/" + caption + ".json"
common.WriteFile(filePath, content+"\n", overwrite) 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 { func loadInbounds(config Config) string {
inbounds := inboundsObject{}
sniff := sniffObject{ sniff := sniffObject{
Enabled: config.Sniff, Enabled: config.Sniff,
RouteOnly: !config.Redirect, RouteOnly: !config.Redirect,
DestOverride: []string{"http", "tls"}, DestOverride: []string{"http", "tls"},
} }
inbounds.Inbounds = append(inbounds.Inbounds, tproxyConfig("tproxy", config.V4TProxyPort, sniff)) var inbounds []interface{}
inbounds.Inbounds = append(inbounds.Inbounds, tproxyConfig("tproxy6", config.V6TProxyPort, sniff)) inbounds = append(inbounds, loadTProxyConfig("tproxy", config.V4TProxyPort, sniff))
inbounds = append(inbounds, loadTProxyConfig("tproxy6", config.V6TProxyPort, sniff))
for tag, port := range config.HttpInbounds { for tag, port := range config.HttpInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, httpConfig(tag, port, sniff)) inbounds = append(inbounds, loadHttpConfig(tag, port, sniff))
} }
for tag, port := range config.SocksInbounds { for tag, port := range config.SocksInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, socksConfig(tag, port, sniff)) inbounds = append(inbounds, loadSocksConfig(tag, port, sniff))
} }
for _, addon := range config.AddOnInbounds { for _, addon := range config.AddOnInbounds {
inbounds.Inbounds = append(inbounds.Inbounds, addon) inbounds = append(inbounds, addon)
} }
return jsonEncode(inbounds) return common.JsonEncode(inboundsObject{
Inbounds: inbounds,
})
} }
func Load(configDir string, exposeDir string, config Config) { func Load(configDir string, exposeDir string, config Config) {
@ -58,7 +51,7 @@ func Load(configDir string, exposeDir string, config Config) {
saveConfig(exposeDir+"/config", "route", routeConfig, false) saveConfig(exposeDir+"/config", "route", routeConfig, false)
saveConfig(exposeDir+"/config", "outbounds", outboundsConfig, false) saveConfig(exposeDir+"/config", "outbounds", outboundsConfig, false)
saveConfig(configDir, "inbounds", loadInbounds(config), true) saveConfig(configDir, "inbounds", loadInbounds(config), true)
saveConfig(configDir, "log", loadLog(config.LogLevel, exposeDir+"/log"), true) saveConfig(configDir, "log", loadLogConfig(config.LogLevel, exposeDir+"/log"), true)
for _, configFile := range common.ListFiles(exposeDir+"/config", ".json") { for _, configFile := range common.ListFiles(exposeDir+"/config", ".json") {
common.CopyFile(exposeDir+"/config/"+configFile, configDir+"/"+configFile) common.CopyFile(exposeDir+"/config/"+configFile, configDir+"/"+configFile)
} }

37
cmd/proxy/object.go

@ -1,37 +0,0 @@
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"`
}

26
main.go

@ -1,6 +1,8 @@
package main package main
import ( import (
"XProxy/cmd/network"
"XProxy/cmd/proxy"
"fmt" "fmt"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -10,4 +12,28 @@ func main() {
fmt.Println("xproxy start") fmt.Println("xproxy start")
network.Load(nil, network.Config{
RouteTable: 100,
TProxyPort: 7288,
Address: "192.168.2.2",
Gateway: "192.168.2.1",
Bypass: make([]string, 0),
}, network.Config{
RouteTable: 106,
TProxyPort: 7289,
Address: "fc00::2",
Gateway: "fc00::1",
Bypass: make([]string, 0),
})
proxy.Load("/etc/xproxy", "/xproxy", proxy.Config{
Sniff: true,
Redirect: true,
V4TProxyPort: 7288,
V6TProxyPort: 7289,
LogLevel: "debug",
HttpInbounds: nil,
SocksInbounds: nil,
AddOnInbounds: nil,
})
} }

Loading…
Cancel
Save