diff --git a/README.md b/README.md index 2b305cc..10374ee 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ export url='https://blog.sunbk201.site/cdn' && sh -c "$(curl -kfsSl $url/install - `-p `: 端口号,默认 1080 - `-f `: 自定义 UA,默认 FFF - `-b `: 自定义绑定监听地址,默认 127.0.0.1 +- `-l `: 日志等级,默认 info,可选:debug + +默认日志位置:`/var/log/ua3f.log` ### 手动启动 ```bash diff --git a/build.sh b/build.sh index 3d52b41..9358db2 100755 --- a/build.sh +++ b/build.sh @@ -1,9 +1,10 @@ #!/bin/sh project_name="ua3f" -release_version="0.0.4" +release_version="0.1.0" +target=cmd/ua3f.go -release_dir=./release +release_dir=./bin rm -rf $release_dir/* mkdir -p $release_dir @@ -14,15 +15,15 @@ gofmt -w ./ for goarch in "amd64" "arm" "arm64" "mipsle" "mips64" "riscv64" "386"; do obj_name=$project_name - GOOS=linux GOARCH=$goarch go build -ldflags="-s -w" + GOOS=linux GOARCH=$goarch go build -ldflags="-s -w" $target tar -zcf $release_dir/$project_name-$release_version-$goarch.tar.gz $obj_name rm -f $obj_name done -GOOS=linux GOARCH="mipsle" GOMIPS=softfloat go build -ldflags="-s -w" +GOOS=linux GOARCH="mipsle" GOMIPS=softfloat go build -ldflags="-s -w" $target tar -zcf $release_dir/$project_name-$release_version-mipsle-softfloat.tar.gz $obj_name rm -f $obj_name -GOOS=linux GOARCH="mipsle" GOMIPS=hardfloat go build -ldflags="-s -w" +GOOS=linux GOARCH="mipsle" GOMIPS=hardfloat go build -ldflags="-s -w" $target tar -zcf $release_dir/$project_name-$release_version-mipsle-hardfloat.tar.gz $obj_name rm -f $obj_name diff --git a/main.go b/cmd/ua3f.go similarity index 70% rename from main.go rename to cmd/ua3f.go index 334c8d7..71d72b5 100644 --- a/main.go +++ b/cmd/ua3f.go @@ -6,37 +6,39 @@ import ( "flag" "fmt" "io" - "log/syslog" "net" "strings" "time" + "ua3f/http" + "ua3f/log" "github.com/hashicorp/golang-lru/v2/expirable" + "github.com/sirupsen/logrus" ) -var version = "0.0.4" +var version = "0.1.0" var payloadByte []byte var cache *expirable.LRU[string, string] func main() { + var payload string var addr string var port int + var loglevel string flag.StringVar(&addr, "b", "127.0.0.1", "bind address (default: 127.0.0.1)") flag.IntVar(&port, "p", 1080, "port") flag.StringVar(&payload, "f", "FFF", "User-Agent") + flag.StringVar(&loglevel, "l", "info", "Log level (default: info)") flag.Parse() - logger, err := syslog.Dial("", "", syslog.LOG_INFO, "UA3F") - if err != nil { - fmt.Println("syslog error:", err) - return - } + log.SetLogConf(loglevel) - printAndLog("UA3F v"+version, logger, syslog.LOG_INFO) - printAndLog(fmt.Sprintf("Port: %d", port), logger, syslog.LOG_INFO) - printAndLog(fmt.Sprintf("User-Agent: %s", payload), logger, syslog.LOG_INFO) + logrus.Info("UA3F v" + version) + logrus.Info(fmt.Sprintf("Port: %d", port)) + logrus.Info(fmt.Sprintf("User-Agent: %s", payload)) + logrus.Info(fmt.Sprintf("Log level: %s", loglevel)) cache = expirable.NewLRU[string, string](100, nil, time.Second*600) @@ -44,32 +46,30 @@ func main() { server, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port)) if err != nil { - printAndLog(fmt.Sprintf("Listen failed: %v", err), logger, syslog.LOG_ERR) + logrus.Fatal("Listen failed: ", err) return } - printAndLog(fmt.Sprintf("Listen on %s:%d", addr, port), logger, syslog.LOG_INFO) + logrus.Info(fmt.Sprintf("Listen on %s:%d", addr, port)) for { client, err := server.Accept() if err != nil { - printAndLog(fmt.Sprintf("Accept failed: %v", err), logger, syslog.LOG_ERR) + logrus.Error("Accept failed: ", err) continue } - // printAndLog(fmt.Sprintf("Accept %s", client.RemoteAddr().String()), logger, syslog.LOG_DEBUG) + logrus.Debug(fmt.Sprintf("Accept %s", client.RemoteAddr().String())) go process(client) } } func process(client net.Conn) { - logger, _ := syslog.Dial("", "", syslog.LOG_INFO, "UA3F") - if err := Socks5Auth(client); err != nil { - printAndLog(fmt.Sprintf("auth error: %v", err), logger, syslog.LOG_ERR) + logrus.Error("Auth failed: ", err) client.Close() return } target, err := Socks5Connect(client) if err != nil { - printAndLog(fmt.Sprintf("connect error: %v", err), logger, syslog.LOG_ERR) + logrus.Error("Connect failed: ", err) client.Close() return } @@ -171,11 +171,10 @@ func Socks5Forward(client, target net.Conn) { } func CopyPileline(dst io.Writer, src io.Reader) { - logger, _ := syslog.Dial("", "", syslog.LOG_INFO, "UA3F") buf := make([]byte, 1024*8) nr, err := src.Read(buf) if err != nil && err != io.EOF { - printAndLog(fmt.Sprintf("read error: %v", err), logger, syslog.LOG_ERR) + logrus.Error("read error: ", err) return } hint := string(buf[0:7]) @@ -194,13 +193,13 @@ func CopyPileline(dst io.Writer, src io.Reader) { return } for { - parser := NewHTTPParser() + parser := http.NewHTTPParser() httpBodyOffset, err := parser.Parse(buf[0:nr]) - for err == ErrMissingData { + for err == http.ErrMissingData { var m int m, err = src.Read(buf[nr:]) if err != nil { - printAndLog(fmt.Sprintf("read error: %v", err), logger, syslog.LOG_ERR) + logrus.Error("read error: ", err) break } nr += m @@ -208,7 +207,7 @@ func CopyPileline(dst io.Writer, src io.Reader) { } value, start, end := parser.FindHeader([]byte("User-Agent")) if value != nil && end > start { - printAndLog(fmt.Sprintf("[%s] Hit User-Agent: %s", string(parser.Host()), string(value)), logger, syslog.LOG_INFO) + logrus.Debug(fmt.Sprintf("[%s] Hit User-Agent: %s", string(parser.Host()), string(value))) for i := start; i < end; i++ { buf[i] = 32 } @@ -219,7 +218,7 @@ func CopyPileline(dst io.Writer, src io.Reader) { buf[start+i] = payloadByte[i] } } else { - printAndLog(fmt.Sprintf("[%s] Not found User-Agent", string(parser.Host())), logger, syslog.LOG_INFO) + logrus.Debug(fmt.Sprintf("[%s] Not found User-Agent", string(parser.Host()))) dst.Write(buf[0:nr]) io.Copy(dst, src) cache.Add(string(dst.(*net.TCPConn).RemoteAddr().String()), string(dst.(*net.TCPConn).RemoteAddr().String())) @@ -232,7 +231,7 @@ func CopyPileline(dst io.Writer, src io.Reader) { _, ew := dst.Write(buf[0:min(httpBodyOffset+bodyLen, nr)]) if ew != nil { - printAndLog(fmt.Sprintf("write error: %v", ew), logger, syslog.LOG_ERR) + logrus.Error("write error: ", ew) break } if httpBodyOffset+bodyLen > nr { @@ -240,12 +239,12 @@ func CopyPileline(dst io.Writer, src io.Reader) { for left > 0 { m, err := src.Read(buf[0:left]) if err != nil { - printAndLog(fmt.Sprintf("read error: %v", err), logger, syslog.LOG_ERR) + logrus.Error("read error: ", err) break } _, ew := dst.Write(buf[0:m]) if ew != nil { - printAndLog(fmt.Sprintf("write error: %v", ew), logger, syslog.LOG_ERR) + logrus.Error("write error: ", ew) break } left -= m @@ -261,7 +260,7 @@ func CopyPileline(dst io.Writer, src io.Reader) { m, err := src.Read(buf[nr:]) nr += m if err != nil && err != io.EOF { - printAndLog(fmt.Sprintf("read error: %v", err), logger, syslog.LOG_ERR) + logrus.Error("read error: ", err) break } if err == io.EOF { @@ -269,29 +268,3 @@ func CopyPileline(dst io.Writer, src io.Reader) { } } } - -func printAndLog(mes string, logger *syslog.Writer, level syslog.Priority) { - fmt.Println(mes) - var err error - switch level { - case syslog.LOG_INFO: - err = logger.Info(mes) - case syslog.LOG_ERR: - err = logger.Err(mes) - case syslog.LOG_DEBUG: - err = logger.Debug(mes) - case syslog.LOG_WARNING: - err = logger.Warning(mes) - case syslog.LOG_CRIT: - err = logger.Crit(mes) - case syslog.LOG_ALERT: - err = logger.Alert(mes) - case syslog.LOG_EMERG: - err = logger.Emerg(mes) - case syslog.LOG_NOTICE: - err = logger.Notice(mes) - } - if err != nil { - fmt.Println("syslog error:", err) - } -} diff --git a/go.mod b/go.mod index 5a3b1f0..4bbacfc 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,9 @@ module ua3f go 1.21.3 -require github.com/hashicorp/golang-lru/v2 v2.0.7 +require ( + github.com/hashicorp/golang-lru/v2 v2.0.7 + github.com/sirupsen/logrus v1.9.3 +) + +require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect diff --git a/go.sum b/go.sum index a33c54a..5ca2774 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,17 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/http.go b/http/http.go similarity index 99% rename from http.go rename to http/http.go index 06d85bd..e573fd7 100644 --- a/http.go +++ b/http/http.go @@ -1,4 +1,4 @@ -package main +package http import ( "bytes" diff --git a/install.sh b/install.sh index f03229a..3d20c9a 100755 --- a/install.sh +++ b/install.sh @@ -16,13 +16,14 @@ getcpucore() { cd /root getcpucore -version=0.0.4 +version=0.1.0 ua3f_tar=ua3f-$version-$cpucore.tar.gz if [ -f "ua3f" ]; then rm "ua3f" fi +chmod ugo+w /var/log if [ -f "/var/log/ua3f.log" ]; then rm "/var/log/ua3f.log" fi @@ -31,7 +32,7 @@ if [ -f "$ua3f_tar" ]; then rm "$ua3f_tar" fi -wget https://fastly.jsdelivr.net/gh/SunBK201/UA3F@master/release/$ua3f_tar +wget https://blog.sunbk201.site/cdn/bin/$ua3f_tar if [ $? -ne 0 ]; then echo "Download UA3F Failed, Please Retry." exit 1 @@ -42,7 +43,7 @@ chmod +x ua3f if [ -f "ua3f.service" ]; then rm "ua3f.service" fi -wget https://fastly.jsdelivr.net/gh/SunBK201/UA3F@master/ua3f.service +wget https://blog.sunbk201.site/cdn/ua3f.service if [ $? -ne 0 ]; then echo "Download ua3f.service Failed, Please Retry." exit 1 diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..ccff8c4 --- /dev/null +++ b/log/log.go @@ -0,0 +1,57 @@ +package log + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "strings" + + "github.com/sirupsen/logrus" +) + +type uctFormatter struct { +} + +func (formatter *uctFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + formatTime := entry.Time.Format("2006-01-02 15:04:05") + b.WriteString(fmt.Sprintf("[%s][%s]: %s\n", formatTime, strings.ToUpper(entry.Level.String()), entry.Message)) + return b.Bytes(), nil +} + +func SetLogConf(level string) { + writer1 := &bytes.Buffer{} + writer2 := os.Stdout + writer3, err := os.OpenFile("/var/log/ua3f.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0755) + if err != nil { + log.Fatalf("create file ua3f.log failed: %v", err) + } + logrus.SetOutput(io.MultiWriter(writer1, writer2, writer3)) + formatter := &uctFormatter{} + logrus.SetFormatter(formatter) + switch level { + case "trace": + logrus.SetLevel(logrus.TraceLevel) + case "debug": + logrus.SetLevel(logrus.DebugLevel) + case "info": + logrus.SetLevel(logrus.InfoLevel) + case "warn": + logrus.SetLevel(logrus.WarnLevel) + case "error": + logrus.SetLevel(logrus.ErrorLevel) + case "fatal": + logrus.SetLevel(logrus.FatalLevel) + case "panic": + logrus.SetLevel(logrus.PanicLevel) + default: + logrus.SetLevel(logrus.InfoLevel) + } +} diff --git a/ua3f.service b/ua3f.service index 2a04f04..e1b1a3a 100755 --- a/ua3f.service +++ b/ua3f.service @@ -5,11 +5,11 @@ START=99 start() { echo "ua3f is starting" if id -u shellclash >/dev/null 2>&1; then - sudo -u shellclash /root/ua3f >/var/log/ua3f.log 2>&1 & + sudo -u shellclash /root/ua3f >/dev/null 2>&1 & elif id -u nobody >/dev/null 2>&1; then - sudo -u nobody /root/ua3f >/var/log/ua3f.log 2>&1 & + sudo -u nobody /root/ua3f >/dev/null 2>&1 & else - /root/ua3f >/var/log/ua3f.log 2>&1 & + /root/ua3f >/dev/null 2>&1 & fi }