mirror of
https://github.com/SunBK201/UA3F.git
synced 2025-12-16 16:57:08 +00:00
feat: use ua regex pattern rule to match target dataflow
This commit is contained in:
parent
221f1e3fab
commit
3c85d70e86
12
README.md
12
README.md
@ -3,7 +3,8 @@
|
||||
UA3F 是下一代 HTTP User-Agent 修改方法,对外作为一个 SOCK5 服务,可以部署在路由器等设备等设备进行透明 UA 修改。
|
||||
|
||||
## 特性
|
||||
- User-Agent 自定义
|
||||
- 支持正则表达式规则匹配修改 User-Agent
|
||||
- 自定义 User-Agent 内容
|
||||
- 与其他网络加速代理工具共存
|
||||
- LRU 高速缓存非 HTTP 域名,加速非 HTTP 流量转发
|
||||
- 支持 LuCI Web 图形页面
|
||||
@ -34,6 +35,14 @@ UA3F 已支持 LuCI Web 页面,可以打开 Services -> UA3F 进行相关配
|
||||
|
||||

|
||||
|
||||
> [!NOTE]
|
||||
> 设置说明:
|
||||
> - Port 为 UA3F 监听端口,默认 `1080`。
|
||||
> - Bind Address 为 UA3F 监听地址,默认 `127.0.0.1`。
|
||||
> - User-Agent 为自定义 User-Agent,默认 `FFF`。
|
||||
> - User-Agent Regex Pattern 为 User-Agent 正则表达式规则。如果流量中的 User-Agent 匹配该正则表达式,则会被修改为 User-Agent 字段的内容,否则不会被修改;如果该字段为空,则所有流量 User-Agent 都会被修改。默认 `(iPhone|iPad|Android|Macintosh|Windows|Linux)`,即只修改携带设备与系统信息的 User-Agent。
|
||||
> - Log Level 为日志等级,默认 `info`, 如果需要调试排查错误可以设置为 `debug`。
|
||||
|
||||
### 作为后台服务运行
|
||||
|
||||
安装脚本执行成功后可通过以下命令启动 UA3F:
|
||||
@ -89,6 +98,7 @@ sudo -u shellcrash /usr/bin/ua3f
|
||||
|
||||
- `-p <port>`: 端口号,默认 1080
|
||||
- `-f <UA>`: 自定义 UA,默认 FFF
|
||||
- `-r <regex>`: 自定义正则匹配 User-Agent, 默认 `(iPhone|iPad|Android|Macintosh|Windows|Linux)`
|
||||
- `-b <bind addr>`: 自定义绑定监听地址,默认 127.0.0.1
|
||||
- `-l <log level>`: 日志等级,默认 info,可选:debug,默认日志位置:`/var/log/ua3f.log`
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
50f53a8171e9156687a497f57ad09403 ./ua3f-0.4.0-386.tar.gz
|
||||
c951b0c15dfb37c13bb0deda5c0cded8 ./ua3f-0.4.0-amd64.tar.gz
|
||||
347864a42fea23c5d7a3d668f2690d84 ./ua3f-0.4.0-arm.tar.gz
|
||||
6d01dee2902d063a1c8acb671bf5252e ./ua3f-0.4.0-arm64.tar.gz
|
||||
f70a52acbb2afe35543e7a68c2c1cf87 ./ua3f-0.4.0-armv7.tar.gz
|
||||
6d01dee2902d063a1c8acb671bf5252e ./ua3f-0.4.0-armv8.tar.gz
|
||||
ca1e2e4942c33b53ad32c84dbc78646c ./ua3f-0.4.0-mips64.tar.gz
|
||||
d7e3fc1947655431b81ab5c66a1a13aa ./ua3f-0.4.0-mipsle-hardfloat.tar.gz
|
||||
95e10592a6e8b260850a824ac307a860 ./ua3f-0.4.0-mipsle-softfloat.tar.gz
|
||||
17862ff6644b1b5cd2176911e3c4624a ./ua3f-0.4.0-mipsle.tar.gz
|
||||
a99dd267a84fa4dcb85b34433ef6987e ./ua3f-0.4.0-riscv64.tar.gz
|
||||
63a160690ef8aaf5770c410ce8a421fd ./ua3f-0.5.0-386.tar.gz
|
||||
4cd727205aa52fd3606b42b60e9e0593 ./ua3f-0.5.0-amd64.tar.gz
|
||||
c4101e2605391754d52b38ceb8ceb1f5 ./ua3f-0.5.0-arm.tar.gz
|
||||
392aa3e532973dc0f2b4f87691dd5572 ./ua3f-0.5.0-arm64.tar.gz
|
||||
d5098bca9f040865d4076de2cc131e44 ./ua3f-0.5.0-armv7.tar.gz
|
||||
392aa3e532973dc0f2b4f87691dd5572 ./ua3f-0.5.0-armv8.tar.gz
|
||||
c0a6f242eff63595a8dc661de1e4390f ./ua3f-0.5.0-mips64.tar.gz
|
||||
a6f7c49f5437d601077856d15b9ba8e7 ./ua3f-0.5.0-mipsle-hardfloat.tar.gz
|
||||
6f966df9a8e5c74a81c3e75d1b06ad9d ./ua3f-0.5.0-mipsle-softfloat.tar.gz
|
||||
3f8974026e09b59d95ee21ed0a9db4b6 ./ua3f-0.5.0-mipsle.tar.gz
|
||||
c86d8d56781d9b5e94805ca76e232dda ./ua3f-0.5.0-riscv64.tar.gz
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/ua3f-0.5.0-386.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-386.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-amd64.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-amd64.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-arm.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-arm.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-arm64.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-arm64.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-armv7.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-armv7.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-armv8.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-armv8.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-mips64.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-mips64.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-mipsle-hardfloat.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-mipsle-hardfloat.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-mipsle-softfloat.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-mipsle-softfloat.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-mipsle.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-mipsle.tar.gz
Normal file
Binary file not shown.
BIN
bin/ua3f-0.5.0-riscv64.tar.gz
Normal file
BIN
bin/ua3f-0.5.0-riscv64.tar.gz
Normal file
Binary file not shown.
2
build.sh
2
build.sh
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
project_name="ua3f"
|
||||
release_version="0.4.0"
|
||||
release_version="0.5.0"
|
||||
target=cmd/ua3f.go
|
||||
dist=./dist
|
||||
release_dir=./bin
|
||||
|
||||
34
cmd/ua3f.go
34
cmd/ua3f.go
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
@ -17,8 +18,10 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var version = "0.4.0"
|
||||
var version = "0.5.0"
|
||||
var payloadByte []byte
|
||||
var uaPattern string
|
||||
var uaRegexp *regexp.Regexp
|
||||
var cache *expirable.LRU[string, string]
|
||||
var HTTP_METHOD = []string{"GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS", "TRACE", "CONNECT"}
|
||||
var whitelist = []string{
|
||||
@ -47,6 +50,7 @@ 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(&loglevel, "l", "info", "Log level (default: info)")
|
||||
flag.Parse()
|
||||
|
||||
@ -55,6 +59,7 @@ func main() {
|
||||
logrus.Info("UA3F v" + version)
|
||||
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("Log level: %s", loglevel))
|
||||
|
||||
cache = expirable.NewLRU[string, string](300, nil, time.Second*600)
|
||||
@ -72,6 +77,11 @@ func main() {
|
||||
return
|
||||
}
|
||||
logrus.Info(fmt.Sprintf("Listen on %s:%d", addr, port))
|
||||
uaRegexp, err = regexp.Compile(uaPattern)
|
||||
if err != nil {
|
||||
logrus.Fatal("Invalid User-Agent Regex Pattern: ", err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
client, err := server.Accept()
|
||||
if err != nil {
|
||||
@ -425,15 +435,29 @@ func CopyPileline(dst io.Writer, src io.Reader, destAddrPort string) {
|
||||
httpBodyOffset, err = parser.Parse(buf[:nr])
|
||||
}
|
||||
value, start, end := parser.FindHeader([]byte("User-Agent"))
|
||||
uaStr := string(value)
|
||||
if value != nil && end > start {
|
||||
if slices.Contains(whitelist, string(value)) {
|
||||
logrus.Debug(fmt.Sprintf("[%s][%s] Hit User-Agent Whitelist: %s, Add LRU Relay Cache, Cache Len: %d", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), string(value), cache.Len()))
|
||||
isInWhiteList := false
|
||||
isMatchUaPattern := true
|
||||
if uaPattern != "" {
|
||||
isMatchUaPattern = uaRegexp.MatchString(uaStr)
|
||||
}
|
||||
if slices.Contains(whitelist, uaStr) {
|
||||
isInWhiteList = true
|
||||
}
|
||||
if isInWhiteList || !isMatchUaPattern {
|
||||
if !isMatchUaPattern {
|
||||
logrus.Debug(fmt.Sprintf("[%s][%s] Not Hit User-Agent Pattern: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), uaStr))
|
||||
}
|
||||
if isInWhiteList {
|
||||
logrus.Debug(fmt.Sprintf("[%s][%s] Hit User-Agent Whitelist: %s, Add LRU Relay Cache, Cache Len: %d", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), uaStr, cache.Len()))
|
||||
cache.Add(destAddrPort, destAddrPort)
|
||||
}
|
||||
dst.Write(buf[0:nr])
|
||||
io.Copy(dst, src)
|
||||
cache.Add(destAddrPort, destAddrPort)
|
||||
return
|
||||
}
|
||||
logrus.Debug(fmt.Sprintf("[%s][%s] Hit User-Agent: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), string(value)))
|
||||
logrus.Debug(fmt.Sprintf("[%s][%s] Hit User-Agent: %s", destAddrPort, src.(*net.TCPConn).RemoteAddr().String(), uaStr))
|
||||
for i := start; i < end; i++ {
|
||||
buf[i] = 32
|
||||
}
|
||||
|
||||
BIN
dist/ua3f_0.4.0-1_386.ipk
vendored
BIN
dist/ua3f_0.4.0-1_386.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_amd64.ipk
vendored
BIN
dist/ua3f_0.4.0-1_amd64.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_arm.ipk
vendored
BIN
dist/ua3f_0.4.0-1_arm.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_arm64.ipk
vendored
BIN
dist/ua3f_0.4.0-1_arm64.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_armv7.ipk
vendored
BIN
dist/ua3f_0.4.0-1_armv7.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_armv8.ipk
vendored
BIN
dist/ua3f_0.4.0-1_armv8.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_mips64.ipk
vendored
BIN
dist/ua3f_0.4.0-1_mips64.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_mipsle-hardfloat.ipk
vendored
BIN
dist/ua3f_0.4.0-1_mipsle-hardfloat.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_mipsle-softfloat.ipk
vendored
BIN
dist/ua3f_0.4.0-1_mipsle-softfloat.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_mipsle.ipk
vendored
BIN
dist/ua3f_0.4.0-1_mipsle.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.4.0-1_riscv64.ipk
vendored
BIN
dist/ua3f_0.4.0-1_riscv64.ipk
vendored
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_386.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_386.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_amd64.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_amd64.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_arm.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_arm.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_arm64.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_arm64.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_armv7.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_armv7.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_armv8.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_armv8.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_mips64.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_mips64.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_mipsle-hardfloat.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_mipsle-hardfloat.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_mipsle-softfloat.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_mipsle-softfloat.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_mipsle.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_mipsle.ipk
vendored
Normal file
Binary file not shown.
BIN
dist/ua3f_0.5.0-1_riscv64.ipk
vendored
Normal file
BIN
dist/ua3f_0.5.0-1_riscv64.ipk
vendored
Normal file
Binary file not shown.
@ -20,7 +20,7 @@ ckcmd() {
|
||||
cd /root
|
||||
getcpucore
|
||||
|
||||
version=0.4.0
|
||||
version=0.5.0
|
||||
ua3f_tar=ua3f-$version-$cpucore.tar.gz
|
||||
|
||||
if id -u shellclash >/dev/null 2>&1; then
|
||||
|
||||
@ -3,7 +3,7 @@ local uci = require("luci.model.uci").cursor()
|
||||
ua3f = Map("ua3f",
|
||||
"UA3F",
|
||||
[[
|
||||
<a href="https://github.com/SunBK201/UA3F" target="_blank">Version: 0.4.0</a>
|
||||
<a href="https://github.com/SunBK201/UA3F" target="_blank">Version: 0.5.0</a>
|
||||
<br>
|
||||
Across the Campus we can reach every corner in the world.
|
||||
]]
|
||||
@ -34,6 +34,8 @@ 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")
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Package: ua3f
|
||||
Version: 0.4.0-1
|
||||
Version: 0.5.0-1
|
||||
Depends: libc, luci-compat
|
||||
Source: /feed/openwrt
|
||||
SourceName: UA3F
|
||||
@ -7,5 +7,5 @@ License: GPL-3.0-only
|
||||
Section: net
|
||||
SourceDateEpoch: 1711267200
|
||||
Architecture: all
|
||||
Installed-Size: 2181120
|
||||
Installed-Size: 2641920
|
||||
Description: Implementation of the new generation of HTTP User-Agent modification methodology.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Package: ua3f
|
||||
Version: 0.4.0-1
|
||||
Version: 0.5.0-1
|
||||
Depends: libc, luci-compat
|
||||
Source: /feed/openwrt
|
||||
SourceName: UA3F
|
||||
@ -7,5 +7,5 @@ License: GPL-3.0-only
|
||||
Section: net
|
||||
SourceDateEpoch: 1711267200
|
||||
Architecture: all
|
||||
Installed-Size: 2181120
|
||||
Installed-Size: 2641920
|
||||
Description: Implementation of the new generation of HTTP User-Agent modification methodology.
|
||||
|
||||
@ -5,4 +5,5 @@ 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 log_level 'info'
|
||||
|
||||
@ -23,6 +23,7 @@ start_service() {
|
||||
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 log_level "main" "log_level" "info"
|
||||
|
||||
chmod o+w /var/log
|
||||
@ -32,6 +33,7 @@ start_service() {
|
||||
procd_append_param command -b "$bind"
|
||||
procd_append_param command -p $port
|
||||
procd_append_param command -f "$ua"
|
||||
procd_append_param command -r "$ua_regex"
|
||||
procd_append_param command -l $log_level
|
||||
|
||||
procd_set_param respawn
|
||||
|
||||
Binary file not shown.
@ -3,7 +3,7 @@ local uci = require("luci.model.uci").cursor()
|
||||
ua3f = Map("ua3f",
|
||||
"UA3F",
|
||||
[[
|
||||
<a href="https://github.com/SunBK201/UA3F" target="_blank">Version: 0.4.0</a>
|
||||
<a href="https://github.com/SunBK201/UA3F" target="_blank">Version: 0.5.0</a>
|
||||
<br>
|
||||
Across the Campus we can reach every corner in the world.
|
||||
]]
|
||||
@ -34,6 +34,8 @@ 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")
|
||||
|
||||
@ -23,6 +23,7 @@ start_service() {
|
||||
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 log_level "main" "log_level" "info"
|
||||
|
||||
chmod o+w /var/log
|
||||
@ -32,6 +33,7 @@ start_service() {
|
||||
procd_append_param command -b "$bind"
|
||||
procd_append_param command -p $port
|
||||
procd_append_param command -f "$ua"
|
||||
procd_append_param command -r "$ua_regex"
|
||||
procd_append_param command -l $log_level
|
||||
|
||||
procd_set_param respawn
|
||||
|
||||
Loading…
Reference in New Issue
Block a user