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
import (
log "github.com/sirupsen/logrus"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
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)
}
log.Debugf("Create folder -> %s", folderPath)
if err := os.MkdirAll(folderPath, 0755); 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()
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)
}
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)
if err := os.WriteFile(filePath, []byte(content), 0644); 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
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)
}
log.Infof("Copy file `%s` => `%s`", source, target)
if IsFileExist(target) {
log.Debugf("File `%s` will be overrided", target)
}
srcFile, err := os.Open(source)
defer srcFile.Close()
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)
defer dstFile.Close()
if err != nil {
log.Panicf("Failed to open file -> %s", target)
}
if _, err = io.Copy(dstFile, srcFile); 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)
log.Debugf("File download `%s` => `%s`", url, file)
resp, err := http.Get(url)
defer resp.Body.Close()
if err != nil {
log.Errorf("Download `%s` error -> %v", url, err)
return
}
output, err := os.OpenFile(file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
defer output.Close()
if err != nil {
log.Panicf("Open `%s` error -> %v", file, err)
}
if _, err = io.Copy(output, resp.Body); err != nil {
log.Panicf("File `%s` save error -> %v", file, err)
}
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
import (
"XProxy/cmd/common"
log "github.com/sirupsen/logrus"
)
var dnsConfig = `{
"dns": {
"servers": [
@ -31,54 +36,92 @@ var outboundsConfig = `{
]
}`
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,
}
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"`
}
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{} {
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 loadHttpConfig(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 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,
}
func loadSocksConfig(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 loadTProxyConfig(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,
}
}

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

@ -2,52 +2,45 @@ package proxy
import (
"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) {
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))
var inbounds []interface{}
inbounds = append(inbounds, loadTProxyConfig("tproxy", config.V4TProxyPort, sniff))
inbounds = append(inbounds, loadTProxyConfig("tproxy6", config.V6TProxyPort, sniff))
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 {
inbounds.Inbounds = append(inbounds.Inbounds, socksConfig(tag, port, sniff))
inbounds = append(inbounds, loadSocksConfig(tag, port, sniff))
}
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) {
@ -58,7 +51,7 @@ func Load(configDir string, exposeDir string, config Config) {
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)
saveConfig(configDir, "log", loadLogConfig(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

@ -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
import (
"XProxy/cmd/network"
"XProxy/cmd/proxy"
"fmt"
log "github.com/sirupsen/logrus"
)
@ -10,4 +12,28 @@ func main() {
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