feat: use ua regex pattern rule to match target dataflow

This commit is contained in:
SunBK201 2024-10-31 14:39:40 +08:00
parent 221f1e3fab
commit 3c85d70e86
58 changed files with 69 additions and 25 deletions

View File

@ -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 进行相关配
![UA3F-LuCI](https://sunbk201.oss-cn-beijing.aliyuncs.com/img/ua3f-luci)
> [!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`

View File

@ -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.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

View File

@ -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
}

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
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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
dist/ua3f_0.5.0-1_riscv64.ipk vendored Normal file

Binary file not shown.

View File

@ -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

View File

@ -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")

View File

@ -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.

View File

@ -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.

View File

@ -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'

View File

@ -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.

View File

@ -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")

View File

@ -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

View File

@ -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'