feat: support regex partial replacement

This commit is contained in:
SunBK201 2024-11-09 15:00:30 +08:00
parent f65f00d196
commit ec53583b35
4 changed files with 36 additions and 11 deletions

View File

@ -29,13 +29,11 @@ main:tab("log", "Log")
port = main:taboption("general", Value, "port", "Port")
port.placeholder = "1080"
bind = main:taboption("general", Value, "bind", "Bind Address")
bind:value("127.0.0.1")
bind:value("0.0.0.0")
ua = main:taboption("general", Value, "ua", "User-Agent")
ua.placeholder = "FFF"
uaRegexPattern = main:taboption("general", Value, "ua_regex", "User-Agent Regex Pattern")
uaRegexPattern.placeholder = "(iPhone|iPad|Android|Macintosh|Windows|Linux)"
log_level = main:taboption("general", ListValue, "log_level", "Log Level")
log_level:value("debug")
log_level:value("info")
@ -43,7 +41,6 @@ log_level:value("warn")
log_level:value("error")
log_level:value("fatal")
log_level:value("panic")
log = main:taboption("log", TextValue, "")
log.readonly = true
log.cfgvalue = function(self, section)
@ -51,9 +48,20 @@ log.cfgvalue = function(self, section)
end
log.rows = 30
ua = main:taboption("general", Value, "ua", "User-Agent")
ua.placeholder = "FFF"
uaRegexPattern = main:taboption("general", Value, "ua_regex", "User-Agent Regex Pattern")
uaRegexPattern.placeholder = "(iPhone|iPad|Android|Macintosh|Windows|Linux|Apple|Mac OS X)"
uaRegexPattern.description = "Regular expression pattern for matching User-Agent"
partialRepalce = main:taboption("general", Flag, "partial_replace", "Partial Replace")
partialRepalce.description = "Replace only the matched part of the User-Agent, only works when User-Agent Regex Pattern is not empty"
partialRepalce.default = "0"
local apply = luci.http.formvalue("cbi.apply")
if apply then
io.popen("/etc/init.d/ua3f restart")
end
-- if apply then
-- io.popen("/etc/init.d/ua3f restart")
-- end
return ua3f

View File

@ -20,10 +20,13 @@ start_service() {
local bind
local ua
local log_level
local ua_regex
local partial_replace
config_get port "main" "port" "1080"
config_get bind "main" "bind" "127.0.0.1"
config_get ua "main" "ua" "FFF"
config_get ua_regex "main" "ua_regex" "(iPhone|iPad|Android|Macintosh|Windows|Linux)"
config_get_bool partial_replace "main" "partial_replace" 0
config_get log_level "main" "log_level" "info"
chmod o+w /var/log
@ -35,6 +38,7 @@ start_service() {
procd_append_param command -f "$ua"
procd_append_param command -r "$ua_regex"
procd_append_param command -l $log_level
[ "$partial_replace" = "1" ] && procd_append_param command -s
procd_set_param respawn
procd_set_param stdout 1

View File

@ -5,5 +5,6 @@ config 'ua3f' 'main'
option port '1080'
option bind '127.0.0.1'
option ua 'FFF'
option ua_regex '(iPhone|iPad|Android|Macintosh|Windows|Linux)'
option ua_regex '(iPhone|iPad|Android|Macintosh|Windows|Linux|Apple|Mac OS X)'
option partial_replace false
option log_level 'info'

View File

@ -19,8 +19,10 @@ import (
var version = "0.5.1"
var payloadByte []byte
var payload string
var uaPattern string
var uaRegexp *regexp2.Regexp
var enablePartialReplace bool
var cache *expirable.LRU[string, string]
var HTTP_METHOD = []string{"GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS", "TRACE", "CONNECT"}
var whitelist = []string{
@ -41,7 +43,6 @@ const RDBUF = 1024 * 8
// }
func main() {
var payload string
var addr string
var port int
var loglevel string
@ -49,7 +50,8 @@ func main() {
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(&uaPattern, "r", "(iPhone|iPad|Android|Macintosh|Windows|Linux)", "UA-Pattern")
flag.StringVar(&uaPattern, "r", "(iPhone|iPad|Android|Macintosh|Windows|Linux|Apple|Mac OS X)", "UA-Pattern")
flag.BoolVar(&enablePartialReplace, "s", false, "Enable Regex Partial Replace")
flag.StringVar(&loglevel, "l", "info", "Log level (default: info)")
flag.Parse()
@ -59,6 +61,7 @@ func main() {
logrus.Info(fmt.Sprintf("Port: %d", port))
logrus.Info(fmt.Sprintf("User-Agent: %s", payload))
logrus.Info(fmt.Sprintf("User-Agent Regex Pattern: %s", uaPattern))
logrus.Info(fmt.Sprintf("Enable Partial Replace: %v", enablePartialReplace))
logrus.Info(fmt.Sprintf("Log level: %s", loglevel))
cache = expirable.NewLRU[string, string](300, nil, time.Second*600)
@ -474,6 +477,15 @@ func CopyPileline(dst io.Writer, src io.Reader, destAddrPort string) {
for i := start; i < end; i++ {
buf[i] = 32
}
if enablePartialReplace && uaRegexp != nil {
newUaHearder, err := uaRegexp.Replace(uaStr, payload, -1, -1)
if err != nil {
logrus.Error(fmt.Sprintf("[%s][%s] User-Agent Replace Error: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), err.Error()))
payloadByte = []byte(payload)
} else {
payloadByte = []byte(newUaHearder)
}
}
for i := range payloadByte {
if start+i >= end {
break