mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-04 08:43:56 +08:00
🤞 Sync 2026-09-30 23:44:05
This commit is contained in:
1 parent
e3fde93105
commit
44bb740ab2
206 files changed
+5736
-2799
No files matched your search
@@ -0,0 +1,52 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=meow
|
||||
PKG_VERSION?=0.21.2
|
||||
PKG_RELEASE?=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
PKG_MAINTAINER:=Independent meow OpenWrt package <noreply@example.invalid>
|
||||
|
||||
define Package/meow
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=meow high-performance rule-based proxy core
|
||||
URL:=https://github.com/meow-rs/meow-rs
|
||||
LICENSE:=MIT
|
||||
endef
|
||||
|
||||
define Package/meow/description
|
||||
meow Rust proxy core built from the upstream commit recorded in UPSTREAM.json.
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/meow/install
|
||||
@test -s ./prebuilt-meow || { echo "ERROR: meow/prebuilt-meow is not populated yet; run build-core.yml first."; exit 1; }
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DIR) $(1)/etc/meow
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_DIR) $(1)/usr/share/meow
|
||||
$(INSTALL_BIN) ./prebuilt-meow $(1)/usr/bin/meow
|
||||
$(INSTALL_BIN) ./files/meow.init $(1)/etc/init.d/meow
|
||||
$(INSTALL_DATA) ./files/meow.config $(1)/etc/config/meow
|
||||
$(INSTALL_DATA) ./files/config.yaml $(1)/etc/meow/config.yaml
|
||||
$(INSTALL_BIN) ./files/gateway.sh $(1)/usr/share/meow/gateway.sh
|
||||
$(INSTALL_BIN) ./files/arp-hijack.sh $(1)/usr/share/meow/arp-hijack.sh
|
||||
$(INSTALL_BIN) ./files/meow-arp.init $(1)/etc/init.d/meow-arp
|
||||
$(INSTALL_BIN) ./files/meow.uci-defaults $(1)/etc/uci-defaults/80_meow
|
||||
endef
|
||||
|
||||
define Package/meow/conffiles
|
||||
/etc/config/meow
|
||||
/etc/meow/config.yaml
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,meow))
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/bin/sh
|
||||
# ARP-based client steering for meow side-router / gateway mode.
|
||||
#
|
||||
# For the LAN clients you SELECT, this periodically sends unicast ARP replies
|
||||
# claiming the network's real gateway IP is at this device's MAC. Those clients
|
||||
# then send their off-LAN traffic here instead, so meow's transparent proxy
|
||||
# handles them WITHOUT any per-client configuration and without changing the
|
||||
# main router's DHCP.
|
||||
#
|
||||
# This is ARP spoofing. Use it only to steer devices you own or administer, on
|
||||
# a network you control. It is OFF by default and touches only the MACs listed
|
||||
# in the `arp_hijack` section of /etc/config/meow — never the whole LAN.
|
||||
#
|
||||
# A client is restored by simply de-selecting it (its ARP cache relearns the
|
||||
# real gateway within its normal timeout once we stop announcing).
|
||||
#
|
||||
# Usage: arp-hijack.sh clients | run | once
|
||||
# Settings come from the `arp_hijack` section of /etc/config/meow.
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
|
||||
clients=""
|
||||
add_client() { clients="$clients $1"; }
|
||||
|
||||
load_config() {
|
||||
config_load meow
|
||||
config_get_bool enabled arp enabled 0
|
||||
config_get interface arp interface lan
|
||||
config_get gateway arp gateway ''
|
||||
config_get interval arp interval 2
|
||||
config_list_foreach arp client add_client
|
||||
|
||||
network_get_device device "$interface"
|
||||
[ -n "$gateway" ] || network_get_gateway gateway "$interface"
|
||||
}
|
||||
|
||||
cmd_clients() {
|
||||
load_config
|
||||
local sel
|
||||
sel=" $(echo "$clients" | tr 'A-F' 'a-f') "
|
||||
printf '['
|
||||
[ -n "$device" ] && ip neigh show dev "$device" 2>/dev/null | awk -v sel="$sel" '
|
||||
{
|
||||
ip=$1; mac=""; st=$NF
|
||||
for (i=1;i<=NF;i++) if ($i=="lladdr") mac=$(i+1)
|
||||
if (mac=="" || index(ip,":")) next
|
||||
lm=tolower(mac)
|
||||
s=(index(sel," " lm " ")?"true":"false")
|
||||
printf "%s{\"ip\":\"%s\",\"mac\":\"%s\",\"state\":\"%s\",\"selected\":%s}", (c++?",":""), ip, mac, st, s
|
||||
}'
|
||||
printf ']\n'
|
||||
}
|
||||
|
||||
mac_to_ip() {
|
||||
ip neigh show dev "$device" 2>/dev/null | awk -v m="$(echo "$1" | tr 'A-F' 'a-f')" '
|
||||
{ mac=""; for (i=1;i<=NF;i++) if ($i=="lladdr") mac=tolower($(i+1))
|
||||
if (mac==m && !index($1,":")) { print $1; exit } }'
|
||||
}
|
||||
|
||||
sweep() {
|
||||
local mac ip
|
||||
for mac in $clients; do
|
||||
ip=$(mac_to_ip "$mac")
|
||||
[ -n "$ip" ] || continue
|
||||
if ! /usr/bin/meow arp-reply "$device" "$gateway" "$mac" "$ip"; then
|
||||
logger -t meow-arp "failed to send unicast reply to $mac ($ip)"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
precheck() {
|
||||
case "$interval" in ''|*[!0-9]*) logger -t meow-arp 'interval must be an integer from 1 to 3600'; return 1 ;; esac
|
||||
[ "$interval" -ge 1 ] && [ "$interval" -le 3600 ] || return 1
|
||||
[ -n "$device" ] || { logger -t meow-arp "no device for interface '$interface'"; return 1; }
|
||||
[ -n "$gateway" ] || { logger -t meow-arp "no gateway for '$interface'; set arp.gateway"; return 1; }
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
clients)
|
||||
cmd_clients
|
||||
;;
|
||||
once)
|
||||
load_config
|
||||
precheck || exit 1
|
||||
sweep
|
||||
;;
|
||||
run)
|
||||
load_config
|
||||
[ "$enabled" -eq 1 ] || { logger -t meow-arp "disabled; not steering"; exit 0; }
|
||||
precheck || exit 1
|
||||
[ -n "$clients" ] || { logger -t meow-arp "no clients selected; idle"; }
|
||||
logger -t meow-arp "steering [$clients ] via $device as gateway $gateway"
|
||||
while :; do
|
||||
sweep || exit 1
|
||||
sleep "$interval"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 clients|run|once" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,44 @@
|
||||
# Default meow-rs configuration shipped with the OpenWrt package.
|
||||
# Edit this file, then restart the service: /etc/init.d/meow restart
|
||||
# Full reference: https://github.com/madeye/meow-rs/blob/main/config.example.yaml
|
||||
|
||||
mixed-port: 7890
|
||||
allow-lan: true
|
||||
bind-address: "0.0.0.0"
|
||||
|
||||
mode: rule
|
||||
log-level: info
|
||||
ipv6: false
|
||||
|
||||
external-controller: 0.0.0.0:9090
|
||||
secret: ""
|
||||
|
||||
routing-mark: 9527
|
||||
|
||||
listeners:
|
||||
- name: tproxy-lan
|
||||
type: tproxy
|
||||
listen: 0.0.0.0
|
||||
port: 7893
|
||||
udp: true
|
||||
firewall: false
|
||||
max-connections: 4096
|
||||
|
||||
sniffer:
|
||||
enable: true
|
||||
override-destination: false
|
||||
sniff:
|
||||
TLS: { ports: [443] }
|
||||
HTTP: { ports: [80] }
|
||||
|
||||
dns:
|
||||
enable: true
|
||||
listen: 0.0.0.0:1053
|
||||
enhanced-mode: fake-ip
|
||||
fake-ip-range: 198.18.0.0/16
|
||||
nameserver:
|
||||
- 223.5.5.5
|
||||
- 8.8.8.8
|
||||
|
||||
rules:
|
||||
- MATCH,DIRECT
|
||||
@@ -0,0 +1,185 @@
|
||||
#!/bin/sh
|
||||
# Transparent-proxy rules for traffic forwarded through this router.
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
|
||||
TABLE="inet meow_gateway"
|
||||
RULES=/var/run/meow/gateway.nft
|
||||
FWMARK=0x2333
|
||||
ROUTING_MARK=0x2537
|
||||
ROUTE_TABLE=233
|
||||
|
||||
load_config() {
|
||||
config_load meow
|
||||
config_get interface tproxy interface lan
|
||||
config_get mode tproxy mode tproxy
|
||||
config_get tproxy_port tproxy tproxy_port 7893
|
||||
config_get_bool dns_hijack tproxy dns_hijack 1
|
||||
config_get dns_port tproxy dns_port 1053
|
||||
config_get_bool ipv6 tproxy ipv6 0
|
||||
config_get bypass tproxy bypass ''
|
||||
config_get bypass_mac tproxy bypass_mac ''
|
||||
bypass_mac=$(echo "$bypass_mac" | tr 'A-F' 'a-f')
|
||||
}
|
||||
|
||||
validate_config() {
|
||||
case "$mode:$ipv6" in redirect:0|redirect:1|tproxy:0) ;; *) return 1 ;; esac
|
||||
for port in "$tproxy_port" "$dns_port"; do
|
||||
case "$port" in ''|*[!0-9]*) return 1 ;; esac
|
||||
[ "$port" -ge 1 ] && [ "$port" -le 65535 ] || return 1
|
||||
done
|
||||
case "$interface" in ''|*[!a-zA-Z0-9_.:-]*) return 1 ;; esac
|
||||
for cidr in $bypass; do
|
||||
case "$cidr" in *[!0-9a-fA-F.:/]*|'') return 1 ;; esac
|
||||
done
|
||||
}
|
||||
|
||||
port_listening() {
|
||||
local hex
|
||||
hex=$(printf '%04X' "$1")
|
||||
grep -qE "^ *[0-9]+: [0-9A-F]+:$hex [0-9A-F]+:[0-9A-F]+ 0A" \
|
||||
/proc/net/tcp /proc/net/tcp6 2>/dev/null
|
||||
}
|
||||
|
||||
gen_rules() {
|
||||
local device="$1" extra4="" extra6="" macs="" cidr mac
|
||||
for cidr in $bypass; do
|
||||
case "$cidr" in
|
||||
*:*) extra6="$extra6, $cidr" ;;
|
||||
*) extra4="$extra4, $cidr" ;;
|
||||
esac
|
||||
done
|
||||
for mac in $bypass_mac; do
|
||||
macs="${macs:+$macs, }$mac"
|
||||
done
|
||||
|
||||
cat <<-NFT
|
||||
table inet meow_gateway {
|
||||
set reserved4 {
|
||||
type ipv4_addr; flags interval; auto-merge
|
||||
elements = {
|
||||
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$extra4
|
||||
}
|
||||
}
|
||||
set reserved6 {
|
||||
type ipv6_addr; flags interval; auto-merge
|
||||
elements = { ::/128, ::1/128, fc00::/7, fe80::/10, ff00::/8$extra6 }
|
||||
}
|
||||
set bypass_src {
|
||||
type ether_addr;
|
||||
NFT
|
||||
[ -n "$macs" ] && echo " elements = { $macs }"
|
||||
cat <<-NFT
|
||||
}
|
||||
|
||||
chain dstnat {
|
||||
type nat hook prerouting priority dstnat - 5; policy accept;
|
||||
iifname != "$device" return
|
||||
meta mark $ROUTING_MARK return
|
||||
ether saddr @bypass_src return
|
||||
NFT
|
||||
[ "$dns_hijack" -eq 1 ] && echo " meta nfproto ipv4 meta l4proto udp th dport 53 redirect to :$dns_port"
|
||||
[ "$ipv6" -eq 1 ] || echo " meta nfproto ipv6 return"
|
||||
cat <<-NFT
|
||||
fib daddr type local return
|
||||
ip daddr @reserved4 return
|
||||
ip6 daddr @reserved6 return
|
||||
meta l4proto tcp redirect to :$tproxy_port
|
||||
}
|
||||
NFT
|
||||
|
||||
if [ "$mode" != redirect ]; then
|
||||
cat <<-NFT
|
||||
|
||||
chain mangle_tproxy {
|
||||
type filter hook prerouting priority mangle; policy accept;
|
||||
iifname != "$device" return
|
||||
meta mark $ROUTING_MARK return
|
||||
ether saddr @bypass_src return
|
||||
NFT
|
||||
[ "$dns_hijack" -eq 1 ] && echo " meta l4proto udp th dport 53 return"
|
||||
[ "$ipv6" -eq 1 ] || echo " meta nfproto ipv6 return"
|
||||
cat <<-NFT
|
||||
fib daddr type local return
|
||||
ip daddr @reserved4 return
|
||||
ip6 daddr @reserved6 return
|
||||
meta l4proto udp socket transparent 1 meta mark set $FWMARK accept
|
||||
meta l4proto udp tproxy to :$tproxy_port meta mark set $FWMARK accept
|
||||
}
|
||||
NFT
|
||||
fi
|
||||
echo "}"
|
||||
}
|
||||
|
||||
route_up() {
|
||||
ip rule add fwmark $FWMARK lookup $ROUTE_TABLE || return 1
|
||||
ip route replace local 0.0.0.0/0 dev lo table $ROUTE_TABLE || return 1
|
||||
if [ "$ipv6" -eq 1 ]; then
|
||||
ip -6 rule add fwmark $FWMARK lookup $ROUTE_TABLE
|
||||
ip -6 route replace local ::/0 dev lo table $ROUTE_TABLE
|
||||
fi
|
||||
}
|
||||
|
||||
route_down() {
|
||||
while ip rule del fwmark $FWMARK lookup $ROUTE_TABLE 2>/dev/null; do :; done
|
||||
ip route flush table $ROUTE_TABLE 2>/dev/null
|
||||
while ip -6 rule del fwmark $FWMARK lookup $ROUTE_TABLE 2>/dev/null; do :; done
|
||||
ip -6 route flush table $ROUTE_TABLE 2>/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
run)
|
||||
child=''
|
||||
trap '[ -z "$child" ] || kill "$child" 2>/dev/null; "$0" down; exit 0' TERM INT
|
||||
"$0" wait & child=$!
|
||||
wait "$child" || exit 1
|
||||
child=''
|
||||
"$0" up || exit 1
|
||||
while :; do sleep 3600 & child=$!; wait "$child"; done
|
||||
;;
|
||||
up)
|
||||
load_config
|
||||
validate_config || { logger -t meow "gateway: invalid configuration"; exit 1; }
|
||||
network_get_device device "$interface"
|
||||
[ -n "$device" ] || exit 1
|
||||
case "$device" in *[!a-zA-Z0-9_.:-]*) exit 1 ;; esac
|
||||
mkdir -p "${RULES%/*}"
|
||||
gen_rules "$device" > "$RULES"
|
||||
nft -c -f "$RULES" || exit 1
|
||||
nft delete table $TABLE 2>/dev/null
|
||||
route_down
|
||||
nft -f "$RULES" || exit 1
|
||||
if [ "$mode" = redirect ]; then
|
||||
logger -t meow "gateway: redirect $device tcp -> :$tproxy_port"
|
||||
else
|
||||
route_up || { "$0" down; exit 1; }
|
||||
logger -t meow "gateway: tproxy $device tcp(redirect)+udp -> :$tproxy_port"
|
||||
fi
|
||||
;;
|
||||
down)
|
||||
nft delete table $TABLE 2>/dev/null
|
||||
route_down
|
||||
;;
|
||||
wait)
|
||||
load_config
|
||||
i=0
|
||||
while [ $i -lt 150 ]; do
|
||||
port_listening "$tproxy_port" && exit 0
|
||||
sleep 0.2
|
||||
i=$((i + 1))
|
||||
done
|
||||
logger -t meow "gateway: :$tproxy_port not listening after 30s"
|
||||
exit 0
|
||||
;;
|
||||
status)
|
||||
nft list table $TABLE
|
||||
;;
|
||||
*)
|
||||
echo "usage: $0 up|down|wait|status" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
USE_PROCD=1
|
||||
START=96
|
||||
STOP=9
|
||||
|
||||
PROG=/usr/share/meow/arp-hijack.sh
|
||||
|
||||
start_service() {
|
||||
local enabled
|
||||
config_load meow
|
||||
config_get_bool enabled arp enabled 0
|
||||
[ "$enabled" -eq 1 ] || return 0
|
||||
|
||||
procd_open_instance meow-arp
|
||||
procd_set_param command "$PROG" run
|
||||
procd_set_param respawn 3600 5 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "meow"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
config meow 'main'
|
||||
option enabled '0'
|
||||
option config_file '/etc/meow/config.yaml'
|
||||
option work_dir '/etc/meow'
|
||||
option panel_port '9090'
|
||||
option secret ''
|
||||
|
||||
config transparent 'tproxy'
|
||||
option enabled '0'
|
||||
option mode 'tproxy'
|
||||
option interface 'lan'
|
||||
option tproxy_port '7893'
|
||||
option dns_hijack '1'
|
||||
option dns_port '1053'
|
||||
option ipv6 '0'
|
||||
|
||||
config arp_hijack 'arp'
|
||||
option enabled '0'
|
||||
option interface 'lan'
|
||||
option gateway ''
|
||||
option interval '2'
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
USE_PROCD=1
|
||||
START=95
|
||||
STOP=10
|
||||
|
||||
PROG=/usr/bin/meow
|
||||
GATEWAY=/usr/share/meow/gateway.sh
|
||||
|
||||
start_service() {
|
||||
local enabled config_file work_dir panel_port secret tproxy controller
|
||||
|
||||
config_load meow
|
||||
config_get_bool enabled main enabled 0
|
||||
config_get config_file main config_file /etc/meow/config.yaml
|
||||
config_get work_dir main work_dir /etc/meow
|
||||
config_get panel_port main panel_port 9090
|
||||
config_get secret main secret ''
|
||||
config_get_bool tproxy tproxy enabled 0
|
||||
|
||||
[ "$enabled" -eq 1 ] || return 0
|
||||
[ "$config_file" = /etc/meow/config.yaml ] && [ "$work_dir" = /etc/meow ] || return 1
|
||||
|
||||
if ! "$PROG" --no-external-plugins -d "$work_dir" -f "$config_file" -t >/dev/null 2>&1; then
|
||||
logger -t meow "config test failed for $config_file, not starting"
|
||||
return 1
|
||||
fi
|
||||
|
||||
controller="127.0.0.1:$panel_port"
|
||||
[ -z "$secret" ] || controller="0.0.0.0:$panel_port"
|
||||
procd_open_instance meow
|
||||
procd_set_param command "$PROG" --no-external-plugins -d "$work_dir" -f "$config_file" \
|
||||
--ext-ctl "$controller"
|
||||
[ -n "$secret" ] && procd_append_param command --secret "$secret"
|
||||
procd_set_param file /etc/config/meow "$config_file"
|
||||
procd_set_param respawn 3600 5 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param limits nofile="1000000 1000000"
|
||||
procd_close_instance
|
||||
|
||||
if [ "$tproxy" -eq 1 ]; then
|
||||
procd_open_instance gateway
|
||||
procd_set_param command "$GATEWAY" run
|
||||
procd_set_param term_timeout 5
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
else
|
||||
"$GATEWAY" down
|
||||
fi
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
"$GATEWAY" down
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "meow"
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
if [ -z "$(uci -q get meow.main.secret)" ]; then
|
||||
secret=$(head -c 32 /dev/urandom | hexdump -v -e '1/1 "%02x"')
|
||||
[ "${#secret}" -eq 64 ] || exit 1
|
||||
uci set "meow.main.secret=$secret"
|
||||
fi
|
||||
if ! uci -q get meow.tproxy >/dev/null; then
|
||||
uci -q batch <<-UCI
|
||||
set meow.tproxy=transparent
|
||||
set meow.tproxy.enabled='0'
|
||||
set meow.tproxy.mode='tproxy'
|
||||
set meow.tproxy.interface='lan'
|
||||
set meow.tproxy.tproxy_port='7893'
|
||||
set meow.tproxy.dns_hijack='1'
|
||||
set meow.tproxy.dns_port='1053'
|
||||
set meow.tproxy.ipv6='0'
|
||||
UCI
|
||||
fi
|
||||
if ! uci -q get meow.arp >/dev/null; then
|
||||
uci -q batch <<-UCI
|
||||
set meow.arp=arp_hijack
|
||||
set meow.arp.enabled='0'
|
||||
set meow.arp.interface='lan'
|
||||
set meow.arp.interval='2'
|
||||
UCI
|
||||
fi
|
||||
uci -q commit meow
|
||||
exit 0
|
||||
Executable
BIN
Binary file not shown.
Reference in new issue
Block a user