mirror of
https://github.com/SunBK201/UA3F.git
synced 2025-12-16 08:44:29 +00:00
chore: bump version to 1.3.0
This commit is contained in:
parent
d8c98a147e
commit
bb92b209ef
2
build.sh
2
build.sh
@ -8,7 +8,7 @@
|
||||
set -e
|
||||
|
||||
project_name="ua3f"
|
||||
release_version="1.2.1"
|
||||
release_version="1.3.0"
|
||||
target=main.go
|
||||
dist=./dist
|
||||
release_dir=./bin
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Package: ua3f
|
||||
Version: 1.2.1-1
|
||||
Version: 1.3.0-1
|
||||
Depends: luci-compat, ipset, iptables, iptables-mod-tproxy, iptables-mod-extra, iptables-mod-nat-extra, kmod-ipt-conntrack, iptables-mod-ipopt
|
||||
Source: /feed/openwrt
|
||||
SourceName: UA3F
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Package: ua3f
|
||||
Version: 1.2.1-1
|
||||
Version: 1.3.0-1
|
||||
Depends: luci-compat, ipset, iptables, iptables-mod-tproxy, iptables-mod-extra, iptables-mod-nat-extra, kmod-ipt-conntrack, iptables-mod-ipopt
|
||||
Source: /feed/openwrt
|
||||
SourceName: UA3F
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=UA3F
|
||||
PKG_VERSION:=1.2.1
|
||||
PKG_VERSION:=1.3.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
# PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
|
||||
@ -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: 1.2.1</a>
|
||||
<a href="https://github.com/SunBK201/UA3F" target="_blank">Version: 1.3.0</a>
|
||||
<br>
|
||||
Across the Campus we can reach every corner in the world.
|
||||
]]
|
||||
|
||||
@ -28,6 +28,8 @@ FAKEIP_RANGE="198.18.0.0/16, 198.18.0.1/15, 28.0.0.1/8"
|
||||
SKIP_PORTS="22,51080,51090"
|
||||
SET_TTL="0"
|
||||
|
||||
server_mode="SOCKS5"
|
||||
|
||||
LOG_FILE="/var/log/ua3f/ua3f.log"
|
||||
|
||||
LOG() {
|
||||
@ -76,6 +78,11 @@ shellclash_running() {
|
||||
}
|
||||
|
||||
set_ua3f_group() {
|
||||
if [ $server_mode = "REDIRECT" ]; then
|
||||
UA3F_GID="0"
|
||||
UA3F_GROUP="root"
|
||||
return
|
||||
fi
|
||||
add_skip_gids "453"
|
||||
if openclash_running; then
|
||||
UA3F_GID="65534"
|
||||
@ -167,6 +174,8 @@ cleanup_tproxy_route() {
|
||||
nft_drop_table() {
|
||||
nft delete table ip "$NFT_TABLE" 2>/dev/null
|
||||
nft delete table inet "$UA3F_TTL_TABLE" 2>/dev/null
|
||||
# nft delete table inet "$NFT_TABLE" 2>/dev/null
|
||||
# nft delete chain inet fw4 "$NFT_TABLE" 2>/dev/null
|
||||
}
|
||||
|
||||
nft_reinit_table() {
|
||||
@ -217,32 +226,50 @@ fw_setup_nft_tproxy_tcp() {
|
||||
nft add rule ip $NFT_TABLE output meta l4proto tcp mark set $UA3F_FWMARK counter accept comment '"default tproxy mark. bypass sc pre pollution"'
|
||||
}
|
||||
|
||||
nft_reinit_table_redirect() {
|
||||
nft_drop_table
|
||||
nft add chain inet fw4 $NFT_TABLE '{ type nat hook prerouting priority dstnat - 1; }' || return 1
|
||||
|
||||
nft "add set inet fw4 $UA3F_LANSET { type ipv4_addr; flags interval; auto-merge; }" || return 1
|
||||
nft "add element inet fw4 $UA3F_LANSET { 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, 224.0.0.0/4, 240.0.0.0/4 }" || return 1
|
||||
}
|
||||
|
||||
fw_setup_nft_redirect_tcp() {
|
||||
nft_reinit_table || return 1
|
||||
|
||||
# PREROUTING -> UA3F
|
||||
nft add chain ip $NFT_TABLE prerouting '{ type nat hook prerouting priority filter + 20; }'
|
||||
nft add chain ip $NFT_TABLE prerouting '{ type nat hook prerouting priority dstnat - 20; }'
|
||||
nft add rule ip $NFT_TABLE prerouting iifname != "br-lan" counter return
|
||||
nft add rule ip $NFT_TABLE prerouting meta l4proto != tcp counter return
|
||||
nft add rule ip $NFT_TABLE prerouting ct direction reply counter return
|
||||
nft add rule ip $NFT_TABLE prerouting mark {$UA3F_SOMARK} counter return comment '"UA3F somark, never hit"'
|
||||
nft add rule ip $NFT_TABLE prerouting mark {0x162} counter return comment '"354"'
|
||||
nft add rule ip $NFT_TABLE prerouting mark {0x1ed4} counter return comment '"sc tproxy mark 7892"'
|
||||
nft add rule ip $NFT_TABLE prerouting ip daddr {$FAKEIP_RANGE} counter return comment '"fakeip range"'
|
||||
nft add rule ip $NFT_TABLE prerouting mark {$UA3F_SOMARK} counter return
|
||||
nft add rule ip $NFT_TABLE prerouting tcp dport {$SKIP_PORTS} return
|
||||
nft add rule ip $NFT_TABLE prerouting ip daddr @$UA3F_LANSET counter return
|
||||
nft add rule ip $NFT_TABLE prerouting tcp dport != {22} counter redirect to :$SERVER_PORT
|
||||
|
||||
# PREROUTING -> UA3F
|
||||
# nft add chain ip $NFT_TABLE prerouting '{ type nat hook prerouting priority filter + 20; }'
|
||||
# nft add rule ip $NFT_TABLE prerouting meta l4proto != tcp counter return
|
||||
# nft add rule ip $NFT_TABLE prerouting ct direction reply counter return
|
||||
# nft add rule ip $NFT_TABLE prerouting mark {$UA3F_SOMARK} counter return comment '"UA3F somark, never hit"'
|
||||
# nft add rule ip $NFT_TABLE prerouting mark {0x162} counter return comment '"354"'
|
||||
# nft add rule ip $NFT_TABLE prerouting mark {0x1ed4} counter return comment '"sc tproxy mark 7892"'
|
||||
# nft add rule ip $NFT_TABLE prerouting ip daddr {$FAKEIP_RANGE} counter return comment '"fakeip range"'
|
||||
# nft add rule ip $NFT_TABLE prerouting tcp dport {$SKIP_PORTS} return
|
||||
# nft add rule ip $NFT_TABLE prerouting ip daddr @$UA3F_LANSET counter return
|
||||
# nft add rule ip $NFT_TABLE prerouting tcp dport != {22} counter redirect to :$SERVER_PORT
|
||||
|
||||
# OUTPUT -> UA3F_OUTPUT
|
||||
nft add chain ip $NFT_TABLE output '{ type nat hook output priority filter + 20; }'
|
||||
nft add rule ip $NFT_TABLE output meta l4proto != tcp counter return
|
||||
nft add rule ip $NFT_TABLE output mark $UA3F_SOMARK counter return comment '"UA3F somark"'
|
||||
nft add rule ip $NFT_TABLE output ip daddr {$FAKEIP_RANGE} counter return
|
||||
nft add rule ip $NFT_TABLE output ip daddr @$UA3F_LANSET counter return
|
||||
nft add rule ip $NFT_TABLE output meta skgid {$SKIP_GIDS} counter return
|
||||
nft add rule ip $NFT_TABLE output tcp dport {$SKIP_PORTS} return
|
||||
nft add rule ip $NFT_TABLE output meta l4proto tcp mark {0x1ed6} counter redirect to :$SERVER_PORT comment '"cap sc meta"'
|
||||
nft add rule ip $NFT_TABLE output meta skgid $UA3F_GID tcp dport != {22} counter redirect to :$SERVER_PORT comment '"cap oc"'
|
||||
nft add rule ip $NFT_TABLE output tcp dport != {22} counter redirect to :$SERVER_PORT comment '"cap scc"'
|
||||
# nft add chain ip $NFT_TABLE output '{ type nat hook output priority filter + 20; }'
|
||||
# nft add rule ip $NFT_TABLE output meta l4proto != tcp counter return
|
||||
# nft add rule ip $NFT_TABLE output mark $UA3F_SOMARK counter return comment '"UA3F somark"'
|
||||
# nft add rule ip $NFT_TABLE output ip daddr {$FAKEIP_RANGE} counter return
|
||||
# nft add rule ip $NFT_TABLE output ip daddr @$UA3F_LANSET counter return
|
||||
# nft add rule ip $NFT_TABLE output meta skgid {$SKIP_GIDS} counter return
|
||||
# nft add rule ip $NFT_TABLE output tcp dport {$SKIP_PORTS} return
|
||||
# nft add rule ip $NFT_TABLE output meta l4proto tcp mark {0x1ed6} counter redirect to :$SERVER_PORT comment '"cap sc meta"'
|
||||
# nft add rule ip $NFT_TABLE output meta skgid $UA3F_GID tcp dport != {22} counter redirect to :$SERVER_PORT comment '"cap oc"'
|
||||
# nft add rule ip $NFT_TABLE output tcp dport != {22} counter redirect to :$SERVER_PORT comment '"cap scc"'
|
||||
}
|
||||
|
||||
setup_ipset_ipt() {
|
||||
@ -315,34 +342,47 @@ fw_setup_ipt_redirect_tcp() {
|
||||
iptables -t nat -D PREROUTING -p tcp -j $UA3F_CHAIN 2>/dev/null
|
||||
iptables -t nat -X $UA3F_CHAIN 2>/dev/null
|
||||
iptables -t nat -N $UA3F_CHAIN
|
||||
iptables -t nat -A PREROUTING -p tcp -j $UA3F_CHAIN
|
||||
iptables -t nat -I PREROUTING -p tcp -j $UA3F_CHAIN
|
||||
iptables -t nat -A $UA3F_CHAIN ! -i "br-lan" -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -m conntrack --ctdir REPLY -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -m mark --mark $UA3F_SOMARK -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -m mark --mark 0x162 -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -m mark --mark 0x1ed4 -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -d 198.18.0.0/16 -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -d 28.0.0.1/8 -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -d 198.18.0.1/15 -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -p tcp -m multiport --dports $SKIP_PORTS -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -m set --match-set $UA3F_LANSET dst -j RETURN
|
||||
iptables -t nat -A $UA3F_CHAIN -p tcp -j REDIRECT --to-ports $SERVER_PORT
|
||||
|
||||
# PREROUTING
|
||||
# iptables -t nat -F $UA3F_CHAIN 2>/dev/null
|
||||
# iptables -t nat -D PREROUTING -p tcp -j $UA3F_CHAIN 2>/dev/null
|
||||
# iptables -t nat -X $UA3F_CHAIN 2>/dev/null
|
||||
# iptables -t nat -N $UA3F_CHAIN
|
||||
# iptables -t nat -A PREROUTING -p tcp -j $UA3F_CHAIN
|
||||
# iptables -t nat -A $UA3F_CHAIN -m conntrack --ctdir REPLY -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -m mark --mark $UA3F_SOMARK -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -m mark --mark 0x162 -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -m mark --mark 0x1ed4 -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -d 198.18.0.0/16 -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -d 28.0.0.1/8 -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -d 198.18.0.1/15 -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -p tcp -m multiport --dports $SKIP_PORTS -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -m set --match-set $UA3F_LANSET dst -j RETURN
|
||||
# iptables -t nat -A $UA3F_CHAIN -p tcp -j REDIRECT --to-ports $SERVER_PORT
|
||||
|
||||
# OUTPUT
|
||||
iptables -t nat -F $UA3F_OUT_CHAIN 2>/dev/null
|
||||
iptables -t nat -D OUTPUT -p tcp -j $UA3F_OUT_CHAIN 2>/dev/null
|
||||
iptables -t nat -X $UA3F_OUT_CHAIN 2>/dev/null
|
||||
iptables -t nat -N $UA3F_OUT_CHAIN
|
||||
iptables -t nat -I OUTPUT -p tcp -j $UA3F_OUT_CHAIN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -m mark --mark $UA3F_SOMARK -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -d 198.18.0.0/16 -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -d 28.0.0.1/8 -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -d 198.18.0.1/15 -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -m multiport --dports $SKIP_PORTS -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -m set --match-set $UA3F_LANSET dst -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -m owner --gid-owner 453 -j RETURN
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -m mark --mark 0x1ed6 -j REDIRECT --to-ports $SERVER_PORT
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -m owner --gid-owner $UA3F_GID -j REDIRECT --to-ports $SERVER_PORT
|
||||
iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -j REDIRECT --to-ports $SERVER_PORT
|
||||
# iptables -t nat -F $UA3F_OUT_CHAIN 2>/dev/null
|
||||
# iptables -t nat -D OUTPUT -p tcp -j $UA3F_OUT_CHAIN 2>/dev/null
|
||||
# iptables -t nat -X $UA3F_OUT_CHAIN 2>/dev/null
|
||||
# iptables -t nat -N $UA3F_OUT_CHAIN
|
||||
# iptables -t nat -I OUTPUT -p tcp -j $UA3F_OUT_CHAIN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -m mark --mark $UA3F_SOMARK -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -d 198.18.0.0/16 -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -d 28.0.0.1/8 -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -d 198.18.0.1/15 -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -m multiport --dports $SKIP_PORTS -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -m set --match-set $UA3F_LANSET dst -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -m owner --gid-owner 453 -j RETURN
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -m mark --mark 0x1ed6 -j REDIRECT --to-ports $SERVER_PORT
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -m owner --gid-owner $UA3F_GID -j REDIRECT --to-ports $SERVER_PORT
|
||||
# iptables -t nat -A $UA3F_OUT_CHAIN -p tcp -j REDIRECT --to-ports $SERVER_PORT
|
||||
}
|
||||
|
||||
cleanup_ipset_ipt() {
|
||||
@ -415,7 +455,7 @@ start_service() {
|
||||
|
||||
LOG "Starting $NAME service..."
|
||||
|
||||
local server_mode port bind ua log_level ua_regex partial_replace set_ttl
|
||||
local port bind ua log_level ua_regex partial_replace set_ttl
|
||||
config_get server_mode "main" "server_mode" "SOCKS5"
|
||||
config_get port "main" "port" "1080"
|
||||
config_get bind "main" "bind" "127.0.0.1"
|
||||
|
||||
@ -6,7 +6,67 @@ import (
|
||||
)
|
||||
|
||||
// HTTP methods used to detect HTTP by request line.
|
||||
var methods = [...]string{"GET", "POST", "HEAD", "CONNECT", "PUT", "DELETE", "OPTIONS", "PATCH", "TRACE"}
|
||||
var methodBytes = [...][]byte{
|
||||
[]byte("GET"),
|
||||
[]byte("POST"),
|
||||
[]byte("HEAD"),
|
||||
[]byte("CONNECT"),
|
||||
[]byte("PUT"),
|
||||
[]byte("DELETE"),
|
||||
[]byte("OPTIONS"),
|
||||
[]byte("PATCH"),
|
||||
[]byte("TRACE"),
|
||||
}
|
||||
|
||||
const maxMethodLen = 7
|
||||
|
||||
type Node struct {
|
||||
next map[byte]*Node
|
||||
end bool
|
||||
}
|
||||
|
||||
var root *Node
|
||||
|
||||
func init() {
|
||||
root = &Node{next: make(map[byte]*Node)}
|
||||
for _, m := range methodBytes {
|
||||
node := root
|
||||
for _, c := range m {
|
||||
if node.next[c] == nil {
|
||||
node.next[c] = &Node{next: make(map[byte]*Node)}
|
||||
}
|
||||
node = node.next[c]
|
||||
}
|
||||
node.end = true
|
||||
}
|
||||
}
|
||||
|
||||
// beginWithHTTPMethod peeks the first few bytes to check for known HTTP method prefixes.
|
||||
func beginWithHTTPMethod(reader *bufio.Reader) (bool, error) {
|
||||
node := root
|
||||
var prevLen int
|
||||
|
||||
for n := 3; n <= maxMethodLen; n++ {
|
||||
buf, err := reader.Peek(n)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for i := prevLen; i < len(buf); i++ {
|
||||
c := buf[i]
|
||||
next, ok := node.next[c]
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
node = next
|
||||
if node.end {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
prevLen = len(buf)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
|
||||
func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
|
||||
@ -18,22 +78,6 @@ func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
|
||||
return method, requestURI, proto, true
|
||||
}
|
||||
|
||||
// beginWithHTTPMethod peeks the first few bytes to check for known HTTP method prefixes.
|
||||
func beginWithHTTPMethod(reader *bufio.Reader) (bool, error) {
|
||||
const maxMethodLen = 7
|
||||
var hint []byte
|
||||
hint, err := reader.Peek(maxMethodLen)
|
||||
if err != nil {
|
||||
}
|
||||
method, _, _ := strings.Cut(string(hint), " ")
|
||||
for _, m := range methods {
|
||||
if method == m {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// SniffHTTP peeks the first few bytes and checks for a known HTTP method prefix.
|
||||
func SniffHTTP(reader *bufio.Reader) (bool, error) {
|
||||
// Fast check: peek first word to see if it's a known HTTP method
|
||||
|
||||
50
src/internal/sniff/http_test.go
Normal file
50
src/internal/sniff/http_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
package sniff
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBeginWithHTTPMethod(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
wantMatch bool
|
||||
wantErr bool
|
||||
}{
|
||||
{"GET method", "GET /index.html HTTP/1.1\r\n", true, false},
|
||||
{"POST method", "POST /submit HTTP/1.1\r\n", true, false},
|
||||
{"HEAD method", "HEAD /abc HTTP/1.0\r\n", true, false},
|
||||
{"PUT method", "PUT /resource HTTP/1.1\r\n", true, false},
|
||||
{"PATCH method", "PATCH /item HTTP/1.1\r\n", true, false},
|
||||
{"OPTIONS method", "OPTIONS * HTTP/1.1\r\n", true, false},
|
||||
{"TRACE method", "TRACE / HTTP/1.1\r\n", true, false},
|
||||
{"CONNECT method", "CONNECT example.com:443 HTTP/1.1\r\n", true, false},
|
||||
{"DELETE method", "DELETE /resource HTTP/1.1\r\n", true, false},
|
||||
{"lowercase method", "get /index.html HTTP/1.1\r\n", false, false},
|
||||
{"non-http prefix", "HELLO WORLD", false, false},
|
||||
{"empty input", "", false, true}, // peek 会返回错误
|
||||
{"short incomplete input", "GE", false, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
reader := bufio.NewReader(bytes.NewBufferString(tt.input))
|
||||
got, err := beginWithHTTPMethod(reader)
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
// differentiate between EOF (expected) and other errors sometimes
|
||||
if !tt.wantErr || !errors.Is(err, io.EOF) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if got != tt.wantMatch {
|
||||
t.Errorf("beginWithHTTPMethod(%q) = %v, want %v", tt.input, got, tt.wantMatch)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"github.com/sunbk201/ua3f/internal/server"
|
||||
)
|
||||
|
||||
const version = "1.2.1"
|
||||
const version = "1.3.0"
|
||||
|
||||
func main() {
|
||||
cfg, showVer := config.Parse()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user