mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 14:43:56 +08:00
🎁 Sync 2026-09-30 11:42:51
This commit is contained in:
1 parent
214a01499a
commit
6c95370452
167 files changed
+3579
-7579
No files matched your search
-129
@@ -1,129 +0,0 @@
|
||||
#
|
||||
# meow —— OpenWrt 包定义
|
||||
#
|
||||
# 本文件由 patches/0001-*.patch 提供;meow/ 下其余文件全部来自上游快照
|
||||
# upstream/openwrt/meow/,由 scripts/apply-patches.sh 生成,请勿手工维护。
|
||||
#
|
||||
# 安装清单与安装/卸载动作逐条对齐上游 openwrt/build-ipk.sh 生成的 opkg control:
|
||||
# /usr/bin/meow、/etc/init.d/meow、/etc/init.d/meow-arp、/etc/config/meow、
|
||||
# /etc/meow/config.yaml、/usr/share/meow/{gateway.sh,arp-hijack.sh}、
|
||||
# /etc/uci-defaults/80_meow、conffiles、postinst、prerm
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
# version.env 位于 feed 根目录;feed 会被 stage 成 feeds/<name>/,
|
||||
# 所以本包目录的上一级就是它。
|
||||
-include $(CURDIR)/../version.env
|
||||
|
||||
MEOW_UPSTREAM_REPO?=meow-rs/meow-rs
|
||||
|
||||
ifeq ($(strip $(MEOW_TAG)),)
|
||||
$(error version.env 缺失或 MEOW_TAG 为空;请先执行 scripts/update-meow-version.sh)
|
||||
endif
|
||||
ifeq ($(strip $(MEOW_TARBALL_SHA256)),)
|
||||
$(error version.env 中 MEOW_TARBALL_SHA256 为空;请重新执行 scripts/update-meow-version.sh)
|
||||
endif
|
||||
|
||||
PKG_NAME:=meow
|
||||
PKG_VERSION:=$(MEOW_VERSION)
|
||||
PKG_RELEASE:=3
|
||||
|
||||
# 直接用上游 release 的 aarch64 静态 musl 二进制,不在 buildroot 内交叉编译 Rust
|
||||
PKG_SOURCE:=$(MEOW_TARBALL_FILE)
|
||||
PKG_SOURCE_URL:=https://github.com/$(MEOW_UPSTREAM_REPO)/releases/download/$(MEOW_TAG)
|
||||
PKG_HASH:=skip
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_MAINTAINER:=zow2023 <https://github.com/zow2023/luci-app-meow>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/meow
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=meow - a mihomo (Clash Meta) compatible proxy kernel in Rust
|
||||
URL:=https://github.com/$(MEOW_UPSTREAM_REPO)
|
||||
DEPENDS:=+libc
|
||||
endef
|
||||
|
||||
define Package/meow/description
|
||||
meow 是 mihomo (Clash Meta) 的 Rust 实现:规则分流、透明代理 (TPROXY/REDIRECT)、
|
||||
DNS snooping 与 DNS 劫持、REST API、内置 Web 面板。
|
||||
本包使用上游 release 提供的 aarch64 静态 musl 二进制,不在 buildroot 内重新编译。
|
||||
上游 ipk 的 control 声明为 Depends: libc
|
||||
透明代理 / 网关模式需自行选中内核模块:kmod-nft-tproxy kmod-nft-socket
|
||||
endef
|
||||
|
||||
预编译二进制:解包后定位 meow 并安装到 $(PKG_BUILD_DIR)/meow
|
||||
|
||||
注意 1:配方里的 shell 变量与命令替换必须写成 $$ 形式($$BIN、$$(find ...))。
|
||||
写成单个 $ 时 make 会先做变量展开:$B 展开为空、$(find ...) 展开为空,
|
||||
命令退化成 BIN=; ... install -m 0755 "IN" ...,报错 install: cannot stat 'IN'。
|
||||
|
||||
注意 2:OpenWrt 的解包命令为 tar -C $(PKG_BUILD_DIR)/.. -xf -,不带
|
||||
--strip-components,tarball 顶层目录会落在 $(PKG_BUILD_DIR) 的同级位置。
|
||||
上游 release 顶层目录是 meow-v<ver>-aarch64-unknown-linux-musl;自建扁平
|
||||
结构 tarball 的 meow 会直接落在 $(PKG_BUILD_DIR)/.. 下。故搜索范围必须
|
||||
同时覆盖 $(PKG_BUILD_DIR) 与其父目录,否则会误报未找到 meow 二进制。
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
if [ ! -f $(PKG_BUILD_DIR)/meow ]; then \
|
||||
BIN=$$(find $(PKG_BUILD_DIR) $(PKG_BUILD_DIR)/.. -maxdepth 3 -type f -name meow 2>/dev/null | head -n1); \
|
||||
[ -n "$$BIN" ] || { echo "ERROR: $(PKG_SOURCE) 内未找到 meow 二进制"; exit 1; }; \
|
||||
echo "meow binary: $$BIN"; \
|
||||
install -m 0755 "$$BIN" $(PKG_BUILD_DIR)/meow; \
|
||||
fi
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/meow/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/meow $(1)/usr/bin/meow
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/meow.init $(1)/etc/init.d/meow
|
||||
$(INSTALL_BIN) ./files/meow-arp.init $(1)/etc/init.d/meow-arp
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./files/meow.config $(1)/etc/config/meow
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/meow
|
||||
$(INSTALL_CONF) ./files/config.yaml $(1)/etc/meow/config.yaml
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/share/meow
|
||||
$(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_DIR) $(1)/etc/uci-defaults
|
||||
$(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
|
||||
|
||||
define Package/meow/postinst
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] && exit 0
|
||||
[ -f /etc/uci-defaults/80_meow ] && { sh /etc/uci-defaults/80_meow; rm -f /etc/uci-defaults/80_meow; }
|
||||
/etc/init.d/meow enable || true
|
||||
# meow-arp 自身按 (默认关闭的) arp_hijack 段自锁,启用它不会真的引流
|
||||
/etc/init.d/meow-arp enable || true
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/meow/prerm
|
||||
#!/bin/sh
|
||||
[ -n "$${IPKG_INSTROOT}" ] && exit 0
|
||||
/etc/init.d/meow-arp stop 2>/dev/null || true
|
||||
/etc/init.d/meow-arp disable 2>/dev/null || true
|
||||
/etc/init.d/meow stop 2>/dev/null || true
|
||||
/etc/init.d/meow disable 2>/dev/null || true
|
||||
exit 0
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,meow))
|
||||
@@ -1,108 +0,0 @@
|
||||
#!/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"
|
||||
}
|
||||
|
||||
# JSON array of the LAN neighbour table, marking which MACs are selected.
|
||||
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'
|
||||
}
|
||||
|
||||
# Current IP for a selected MAC (resolved fresh each sweep; DHCP may move it).
|
||||
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
|
||||
# ARP reply: "gateway is at <our MAC>", unicast to the client.
|
||||
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
|
||||
@@ -1,82 +0,0 @@
|
||||
# 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
|
||||
|
||||
# Combined HTTP + SOCKS5 proxy for LAN clients.
|
||||
mixed-port: 7890
|
||||
allow-lan: true
|
||||
bind-address: "0.0.0.0"
|
||||
|
||||
mode: rule
|
||||
log-level: info
|
||||
ipv6: false
|
||||
|
||||
# REST API + built-in web panel (served at /ui). The init script overrides
|
||||
# the address with `--ext-ctl 0.0.0.0:<panel_port>` and, when set, the secret
|
||||
# with `--secret <secret>` from /etc/config/meow, so LuCI always knows how to
|
||||
# reach it. OpenWrt's default firewall still blocks WAN-side access.
|
||||
external-controller: 0.0.0.0:9090
|
||||
secret: ""
|
||||
|
||||
# SO_MARK for DIRECT sockets (loop avoidance on Linux).
|
||||
routing-mark: 9527
|
||||
|
||||
# Transparent-proxy listener for forwarded LAN traffic (gateway / side-router
|
||||
# mode, enabled in LuCI or via `uci set meow.tproxy.enabled=1`). Must bind a
|
||||
# non-loopback IPv4 address; the port must match `tproxy_port` in
|
||||
# /etc/config/meow.
|
||||
#
|
||||
# `firewall: false` leaves all rule management to gateway.sh (this package's
|
||||
# nftables rules) — meow makes no nft calls itself. `udp: true` enables UDP
|
||||
# TPROXY, which requires `firewall: false`, an IPv4 listen, and the
|
||||
# deployer-owned fwmark + policy routing that gateway.sh's `tproxy` mode sets
|
||||
# up. In `redirect` mode gateway.sh uses nat REDIRECT and only TCP is proxied;
|
||||
# the same listener accepts it (UDP is simply never delivered).
|
||||
listeners:
|
||||
- name: tproxy-lan
|
||||
type: tproxy
|
||||
listen: 0.0.0.0
|
||||
port: 7893
|
||||
udp: true
|
||||
firewall: false
|
||||
# A gateway serves many concurrent flows from every LAN client; the 256
|
||||
# default saturates under a few busy devices and stalls new connections.
|
||||
# 0 = unlimited.
|
||||
max-connections: 4096
|
||||
|
||||
# Recover hostnames for connections made to raw IPs.
|
||||
sniffer:
|
||||
enable: true
|
||||
override-destination: false
|
||||
sniff:
|
||||
TLS: { ports: [443] }
|
||||
HTTP: { ports: [80] }
|
||||
|
||||
dns:
|
||||
enable: true
|
||||
# dnsmasq owns :53; meow's resolver listens on 1053. LAN DNS is redirected
|
||||
# here when transparent proxy + DNS hijack are enabled (`dns_port`).
|
||||
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
|
||||
|
||||
# Add your proxies and groups here, e.g.:
|
||||
# proxies:
|
||||
# - name: "ss-example"
|
||||
# type: ss
|
||||
# server: 1.2.3.4
|
||||
# port: 8388
|
||||
# cipher: aes-256-gcm
|
||||
# password: "your-password"
|
||||
# udp: true
|
||||
#
|
||||
# proxy-groups:
|
||||
# - name: "PROXY"
|
||||
# type: select
|
||||
# proxies: ["ss-example", "DIRECT"]
|
||||
|
||||
rules:
|
||||
- MATCH,DIRECT
|
||||
@@ -1,234 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Transparent-proxy rules for traffic forwarded through this router
|
||||
# (gateway or side-router mode). meow's built-in `inet meow_tproxy` table only
|
||||
# covers the router's own output traffic; this adds `inet meow_gateway`, which
|
||||
# hooks prerouting on the LAN device. See docs/tproxy-gateway.md.
|
||||
#
|
||||
# Modes (`option mode`):
|
||||
# tproxy REDIRECT for TCP + kernel TPROXY for UDP (default). meow's TCP
|
||||
# listener recovers the original destination via SO_ORIGINAL_DST,
|
||||
# which only nat REDIRECT populates, so TCP is never sent through
|
||||
# kernel TPROXY; UDP has a real IP_TRANSPARENT listener.
|
||||
# redirect nat REDIRECT, TCP only
|
||||
#
|
||||
# Usage: gateway.sh up|down|wait|status
|
||||
# Settings come from the `tproxy` section of /etc/config/meow.
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
|
||||
TABLE="inet meow_gateway"
|
||||
RULES=/var/run/meow/gateway.nft
|
||||
# Two marks, deliberately different (see docs/tproxy-gateway.md):
|
||||
# FWMARK tags the UDP datagrams the mangle chain hands to the TPROXY
|
||||
# listener; a policy route delivers those marked packets
|
||||
# locally. TCP never uses it.
|
||||
# ROUTING_MARK meow's own outbound sockets carry this (SO_MARK, from the
|
||||
# YAML `routing-mark`), so both capture chains RETURN on it and
|
||||
# meow's own traffic is never re-proxied into a loop. This MUST
|
||||
# equal `routing-mark` in the meow YAML config (default 9527).
|
||||
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) ;; *)
|
||||
logger -t meow 'gateway: invalid mode/IPv6 combination; IPv6 requires redirect mode'; 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
|
||||
local h='[0-9a-f][0-9a-f]'
|
||||
for mac in $bypass_mac; do
|
||||
case "$mac" in $h:$h:$h:$h:$h:$h) ;; *) return 1 ;; esac
|
||||
done
|
||||
}
|
||||
|
||||
port_listening() {
|
||||
# /proc/net/tcp{,6} list local ports in hex; state 0A is LISTEN.
|
||||
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
|
||||
|
||||
# TCP goes through nat REDIRECT in BOTH modes (dstnat chain): meow's TCP
|
||||
# listener recovers the original destination with SO_ORIGINAL_DST, which
|
||||
# needs the conntrack DNAT that REDIRECT creates. Kernel TPROXY leaves no
|
||||
# conntrack entry, so a TPROXY'd TCP flow resolves to the listener's own
|
||||
# address and meow dials itself — a saturating loop. UDP has no REDIRECT
|
||||
# equivalent and a real IP_TRANSPARENT listener, so it uses TPROXY.
|
||||
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 }
|
||||
}
|
||||
# LAN clients (by MAC) that skip both capture and the DNS hijack.
|
||||
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
|
||||
|
||||
# redirect mode stops at TCP; tproxy mode adds the UDP TPROXY chain.
|
||||
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" ] || {
|
||||
logger -t meow "gateway: no device for interface '$interface'"
|
||||
exit 1
|
||||
}
|
||||
case "$device" in *[!a-zA-Z0-9_.:-]*) exit 1 ;; esac
|
||||
mkdir -p "${RULES%/*}"
|
||||
gen_rules "$device" > "$RULES"
|
||||
if ! nft -c -f "$RULES"; then
|
||||
logger -t meow 'gateway: invalid rules or missing kernel support; install kmod-nft-socket kmod-nft-tproxy (opkg install, or apk add on newer OpenWrt)'
|
||||
exit 1
|
||||
fi
|
||||
nft delete table $TABLE 2>/dev/null
|
||||
route_down
|
||||
if ! nft -f "$RULES"; then
|
||||
logger -t meow "gateway: failed to load $RULES"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$mode" = redirect ]; then
|
||||
logger -t meow "gateway: redirect $device tcp -> :$tproxy_port"
|
||||
else
|
||||
route_up || { "$0" down; logger -t meow "gateway: policy routing failed"; 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)
|
||||
# Block until meow binds the tproxy listener (30s cap, then load
|
||||
# anyway so the rules fail closed rather than leaking traffic).
|
||||
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
|
||||
@@ -1,29 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# procd init for meow's ARP client-steering loop (arp-hijack.sh). Self-gates on
|
||||
# the `arp_hijack` section of /etc/config/meow: does nothing unless enabled and
|
||||
# at least the feature is turned on. Separate from the meow service so steering
|
||||
# can be toggled without restarting the proxy.
|
||||
|
||||
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"
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
config meow 'main'
|
||||
# Set to '1' to start meow at boot and via /etc/init.d/meow start.
|
||||
option enabled '0'
|
||||
# meow YAML configuration (proxies, rules, DNS, listeners, ...).
|
||||
option config_file '/etc/meow/config.yaml'
|
||||
# Working directory for GeoIP databases, caches, downloaded rulesets.
|
||||
option work_dir '/etc/meow'
|
||||
# Port of the REST API / built-in web panel. Passed to meow as
|
||||
# `--ext-ctl 0.0.0.0:<port>`, overriding `external-controller` in the YAML.
|
||||
option panel_port '9090'
|
||||
# A random API secret is generated on install. Empty binds to loopback only.
|
||||
# When non-empty it is passed as `--secret`, overriding
|
||||
# `secret:` in the YAML; LuCI uses it to talk to the API and the panel.
|
||||
option secret ''
|
||||
|
||||
# Transparent proxy for forwarded LAN traffic (gateway / side-router mode).
|
||||
# Loads an nftables table `inet meow_gateway` that hands traffic arriving on
|
||||
# the LAN interface to meow's tproxy listener and hijacks DNS to meow's
|
||||
# resolver. The YAML config must declare a matching non-loopback tproxy
|
||||
# listener and DNS listener (the shipped default config does).
|
||||
config transparent 'tproxy'
|
||||
option enabled '0'
|
||||
# 'tproxy': REDIRECT for TCP + kernel TPROXY for UDP. 'redirect': TCP only.
|
||||
option mode 'tproxy'
|
||||
# Logical OpenWrt interface whose clients are proxied.
|
||||
option interface 'lan'
|
||||
# Port of the `type: tproxy` listener in the YAML config.
|
||||
option tproxy_port '7893'
|
||||
# Redirect LAN DNS (port 53, any resolver) to meow's DNS listener.
|
||||
option dns_hijack '1'
|
||||
# Port of meow's DNS listener (`dns.listen` in the YAML config).
|
||||
option dns_port '1053'
|
||||
# Also proxy IPv6. Off by default: fake-ip suppresses AAAA.
|
||||
option ipv6 '0'
|
||||
# Extra destination CIDRs that bypass the proxy (besides reserved ranges).
|
||||
# list bypass '203.0.113.0/24'
|
||||
# LAN client MACs whose traffic bypasses the proxy entirely (no capture, no
|
||||
# DNS hijack). Managed from LuCI (Services -> meow -> Clients).
|
||||
# list bypass_mac 'aa:bb:cc:dd:ee:ff'
|
||||
|
||||
# ARP-based client steering (side-router / gateway mode). For SELECTED clients,
|
||||
# periodically announce this device as the LAN gateway so their traffic is
|
||||
# transparently proxied without per-client config. This is ARP spoofing: use it
|
||||
# only for devices you administer on a network you control. OFF by default; only
|
||||
# the MACs listed here are ever touched. Managed from LuCI (Services -> meow ->
|
||||
# Clients). Uses meow's built-in unicast ARP sender.
|
||||
config arp_hijack 'arp'
|
||||
option enabled '0'
|
||||
# LAN interface whose clients are steered.
|
||||
option interface 'lan'
|
||||
# Gateway IP to impersonate. Empty = this interface's real gateway.
|
||||
option gateway ''
|
||||
# Seconds between ARP announcements (caches expire, so we re-announce).
|
||||
option interval '2'
|
||||
# Selected client MACs (one per line). Managed from the Clients tab.
|
||||
# list client 'aa:bb:cc:dd:ee:ff'
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# procd init script for meow-rs.
|
||||
# Service settings live in /etc/config/meow (UCI); the proxy configuration
|
||||
# itself is the regular meow YAML file (default /etc/meow/config.yaml).
|
||||
|
||||
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 ] || {
|
||||
logger -t meow 'managed service requires /etc/meow/config.yaml and 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"
|
||||
# Restart when either the UCI service settings or the YAML config change.
|
||||
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
|
||||
# A supervised instance owns the wait and rules, including teardown.
|
||||
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
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Add sections introduced after the first release to preserved configs.
|
||||
# Preserve existing credentials on upgrades; initialize an empty install.
|
||||
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
|
||||
Reference in new issue
Block a user