parent
773b48e073
commit
fabf3933ff
102
nikki/Makefile
Normal file
102
nikki/Makefile
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=nikki
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE_PROTO:=git
|
||||||
|
PKG_SOURCE_URL:=https://github.com/MetaCubeX/mihomo.git
|
||||||
|
PKG_SOURCE_DATE:=2025-01-21
|
||||||
|
PKG_SOURCE_VERSION:=b69e52d4d72846b8201a4073ed68c4c332c40db9
|
||||||
|
PKG_MIRROR_HASH:=33ecc27b647a62920d752a877c1a2812d93ed375a332ceac6890b5b070c7aacc
|
||||||
|
|
||||||
|
PKG_LICENSE:=GPL3.0+
|
||||||
|
PKG_MAINTAINER:=Joseph Mory <morytyann@gmail.com>
|
||||||
|
|
||||||
|
PKG_BUILD_DEPENDS:=golang/host
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
PKG_BUILD_FLAGS:=no-mips16
|
||||||
|
|
||||||
|
PKG_BUILD_VERSION:=alpha-b69e52d
|
||||||
|
PKG_BUILD_TIME:=$(shell date -u -Iseconds)
|
||||||
|
|
||||||
|
GO_PKG:=github.com/metacubex/mihomo
|
||||||
|
GO_PKG_LDFLAGS_X:=$(GO_PKG)/constant.Version=$(PKG_BUILD_VERSION) $(GO_PKG)/constant.BuildTime=$(PKG_BUILD_TIME)
|
||||||
|
GO_PKG_TAGS:=with_gvisor
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||||
|
|
||||||
|
define Package/nikki
|
||||||
|
SECTION:=net
|
||||||
|
CATEGORY:=Network
|
||||||
|
TITLE:=A rule based proxy in Go.
|
||||||
|
URL:=https://wiki.metacubex.one
|
||||||
|
DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +curl +yq firewall4 +ip-full +kmod-inet-diag +kmod-nft-tproxy +kmod-tun
|
||||||
|
USERID:=root:nikki=1206
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nikki/description
|
||||||
|
A rule based proxy in Go.
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nikki/conffiles
|
||||||
|
/etc/config/nikki
|
||||||
|
/etc/nikki/mixin.yaml
|
||||||
|
/etc/nikki/nftables/reserved_ip.nft
|
||||||
|
/etc/nikki/nftables/reserved_ip6.nft
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nikki/install
|
||||||
|
$(call GoPackage/Package/Install/Bin,$(1))
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki/scripts
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki/nftables
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki/profiles
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki/subscriptions
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki/run
|
||||||
|
$(INSTALL_DIR) $(1)/etc/nikki/run/ui
|
||||||
|
|
||||||
|
$(INSTALL_DATA) $(CURDIR)/files/mixin.yaml $(1)/etc/nikki/mixin.yaml
|
||||||
|
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/scripts/include.sh $(1)/etc/nikki/scripts/include.sh
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/scripts/firewall_include.sh $(1)/etc/nikki/scripts/firewall_include.sh
|
||||||
|
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/nftables/hijack.nft $(1)/etc/nikki/nftables/hijack.nft
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/nftables/reserved_ip.nft $(1)/etc/nikki/nftables/reserved_ip.nft
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/nftables/reserved_ip6.nft $(1)/etc/nikki/nftables/reserved_ip6.nft
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/nftables/geoip_cn.nft $(1)/etc/nikki/nftables/geoip_cn.nft
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/nftables/geoip6_cn.nft $(1)/etc/nikki/nftables/geoip6_cn.nft
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
|
$(INSTALL_CONF) $(CURDIR)/files/nikki.conf $(1)/etc/config/nikki
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/etc/init.d
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/nikki.init $(1)/etc/init.d/nikki
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/uci-defaults/firewall.sh $(1)/etc/uci-defaults/99_firewall_nikki
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/uci-defaults/init.sh $(1)/etc/uci-defaults/99_init_nikki
|
||||||
|
$(INSTALL_BIN) $(CURDIR)/files/uci-defaults/migrate.sh $(1)/etc/uci-defaults/99_migrate_nikki
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
|
||||||
|
$(INSTALL_DATA) $(CURDIR)/files/nikki.upgrade $(1)/lib/upgrade/keep.d/nikki
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nikki/postrm
|
||||||
|
#!/bin/sh
|
||||||
|
if [ -z $${IPKG_INSTROOT} ]; then
|
||||||
|
uci -q batch <<-EOF > /dev/null
|
||||||
|
del firewall.nikki
|
||||||
|
commit firewall
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Build/Prepare
|
||||||
|
$(Build/Prepare/Default)
|
||||||
|
$(RM) -r $(PKG_BUILD_DIR)/rules/logic_test
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call GoBinPackage,nikki))
|
||||||
|
$(eval $(call BuildPackage,nikki))
|
28
nikki/files/mixin.yaml
Normal file
28
nikki/files/mixin.yaml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Mixin File
|
||||||
|
# You can set any mihomo profile's config at here, it will mixin to the profile.
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# global-client-fingerprint: chrome # set fingerprint for TLS transport
|
||||||
|
# experimental: # experimental config
|
||||||
|
# quic-go-disable-gso: false # disable quic-go GSO support
|
||||||
|
# quic-go-disable-ecn: false # disable quic-go ECN support
|
||||||
|
# dialer-ip4p-convert: false # IP4P support
|
||||||
|
# proxies: # overwrite proxies
|
||||||
|
# - name: "PROXY"
|
||||||
|
# type: ss
|
||||||
|
# server: proxy.example.com
|
||||||
|
# port: 443
|
||||||
|
# cipher: chacha20-ietf-poly1305
|
||||||
|
# password: "password"
|
||||||
|
# rules: # overwrite rules
|
||||||
|
# - DOMAIN,google.com,PROXY
|
||||||
|
# - DOMAIN-SUFFIX,google.com,PROXY
|
||||||
|
# - DOMAIN-KEYWORD,google,PROXY
|
||||||
|
# - DOMAIN-REGEX,^google.*com,PROXY
|
||||||
|
# - GEOSITE,google,PROXY
|
||||||
|
# - GEOSITE,cn,DIRECT
|
||||||
|
# - IP-CIDR,8.8.8.8/32,DIRECT,no-resolve
|
||||||
|
# - GEOIP,telegram,DIRECT
|
||||||
|
# - GEOIP,cn,DIRECT
|
||||||
|
# - Match,PROXY
|
3134
nikki/files/nftables/geoip6_cn.nft
Normal file
3134
nikki/files/nftables/geoip6_cn.nft
Normal file
File diff suppressed because it is too large
Load Diff
5222
nikki/files/nftables/geoip_cn.nft
Normal file
5222
nikki/files/nftables/geoip_cn.nft
Normal file
File diff suppressed because it is too large
Load Diff
243
nikki/files/nftables/hijack.nft
Normal file
243
nikki/files/nftables/hijack.nft
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
|
||||||
|
table inet nikki {
|
||||||
|
set bypass_user {
|
||||||
|
type uid
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set bypass_group {
|
||||||
|
type gid
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
elements = {
|
||||||
|
$NIKKI_GROUP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set bypass_dscp {
|
||||||
|
type dscp
|
||||||
|
flags interval
|
||||||
|
}
|
||||||
|
|
||||||
|
set dns_hijack_nfproto {
|
||||||
|
type nf_proto
|
||||||
|
flags interval
|
||||||
|
}
|
||||||
|
|
||||||
|
set proxy_nfproto {
|
||||||
|
type nf_proto
|
||||||
|
flags interval
|
||||||
|
}
|
||||||
|
|
||||||
|
set china_ip {
|
||||||
|
type ipv4_addr
|
||||||
|
flags interval
|
||||||
|
}
|
||||||
|
|
||||||
|
set china_ip6 {
|
||||||
|
type ipv6_addr
|
||||||
|
flags interval
|
||||||
|
}
|
||||||
|
|
||||||
|
set reserved_ip {
|
||||||
|
type ipv4_addr
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set reserved_ip6 {
|
||||||
|
type ipv6_addr
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set proxy_dport {
|
||||||
|
type inet_proto . inet_service
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set acl_ip {
|
||||||
|
type ipv4_addr
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set acl_ip6 {
|
||||||
|
type ipv6_addr
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set acl_mac {
|
||||||
|
type ether_addr
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
set acl_interface {
|
||||||
|
type ifname
|
||||||
|
flags interval
|
||||||
|
auto-merge
|
||||||
|
}
|
||||||
|
|
||||||
|
chain router_dns_hijack {
|
||||||
|
meta skuid @bypass_user counter return
|
||||||
|
meta skgid @bypass_group counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter redirect to :$DNS_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain all_dns_hijack {
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter redirect to :$DNS_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain allow_dns_hijack {
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 ip saddr @acl_ip counter redirect to :$DNS_PORT
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 ip6 saddr @acl_ip6 counter redirect to :$DNS_PORT
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 ether saddr @acl_mac counter redirect to :$DNS_PORT
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 iifname @acl_interface counter redirect to :$DNS_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain block_dns_hijack {
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 ip saddr @acl_ip counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 ip6 saddr @acl_ip6 counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 ether saddr @acl_mac counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 iifname @acl_interface counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter redirect to :$DNS_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain router_redirect {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp counter redirect to :$REDIR_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain all_redirect {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp counter redirect to :$REDIR_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain allow_redirect {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp ip saddr @acl_ip counter redirect to :$REDIR_PORT
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp ip6 saddr @acl_ip6 counter redirect to :$REDIR_PORT
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp ether saddr @acl_mac counter redirect to :$REDIR_PORT
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp iifname @acl_interface counter redirect to :$REDIR_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain block_redirect {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp ip saddr @acl_ip counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp ip6 saddr @acl_ip6 counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp ether saddr @acl_mac counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp iifname @acl_interface counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto tcp counter redirect to :$REDIR_PORT
|
||||||
|
}
|
||||||
|
|
||||||
|
chain router_tproxy {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK counter
|
||||||
|
}
|
||||||
|
|
||||||
|
chain all_tproxy {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept
|
||||||
|
}
|
||||||
|
|
||||||
|
chain allow_tproxy {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip meta mark set mark ^ $FW_MARK tproxy ip to :$TPROXY_PORT counter accept
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 meta mark set mark ^ $FW_MARK tproxy ip6 to :$TPROXY_PORT counter accept
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept
|
||||||
|
}
|
||||||
|
|
||||||
|
chain block_tproxy {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK tproxy to :$TPROXY_PORT counter accept
|
||||||
|
}
|
||||||
|
|
||||||
|
chain router_tun {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK counter
|
||||||
|
}
|
||||||
|
|
||||||
|
chain all_tun {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK counter
|
||||||
|
}
|
||||||
|
|
||||||
|
chain allow_tun {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip meta mark set mark ^ $FW_MARK counter
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 meta mark set mark ^ $FW_MARK counter
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac meta mark set mark ^ $FW_MARK counter
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface meta mark set mark ^ $FW_MARK counter
|
||||||
|
}
|
||||||
|
|
||||||
|
chain block_tun {
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip saddr @acl_ip counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ip6 saddr @acl_ip6 counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } ether saddr @acl_mac counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } iifname @acl_interface counter return
|
||||||
|
meta nfproto @proxy_nfproto meta l4proto { tcp, udp } meta mark set mark ^ $FW_MARK counter
|
||||||
|
}
|
||||||
|
|
||||||
|
chain dstnat {
|
||||||
|
type nat hook prerouting priority dstnat + 1; policy accept;
|
||||||
|
fib daddr type { local, multicast, broadcast, anycast } counter return
|
||||||
|
ct direction reply counter return
|
||||||
|
ip daddr @reserved_ip counter return
|
||||||
|
ip6 daddr @reserved_ip6 counter return
|
||||||
|
ip daddr @china_ip counter return
|
||||||
|
ip6 daddr @china_ip6 counter return
|
||||||
|
meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return
|
||||||
|
meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return
|
||||||
|
meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return
|
||||||
|
meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return
|
||||||
|
}
|
||||||
|
|
||||||
|
chain nat_output {
|
||||||
|
type nat hook output priority filter; policy accept;
|
||||||
|
meta skuid @bypass_user counter return
|
||||||
|
meta skgid @bypass_group counter return
|
||||||
|
fib daddr type { local, multicast, broadcast, anycast } counter return
|
||||||
|
ct direction reply counter return
|
||||||
|
ip daddr @reserved_ip counter return
|
||||||
|
ip6 daddr @reserved_ip6 counter return
|
||||||
|
ip daddr @china_ip counter return
|
||||||
|
ip6 daddr @china_ip6 counter return
|
||||||
|
meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return
|
||||||
|
meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return
|
||||||
|
meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return
|
||||||
|
meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return
|
||||||
|
}
|
||||||
|
|
||||||
|
chain mangle_prerouting {
|
||||||
|
type filter hook prerouting priority mangle; policy accept;
|
||||||
|
meta l4proto { tcp, udp } iifname lo meta mark & $FW_MARK_MASK == $FW_MARK tproxy to :$TPROXY_PORT counter accept
|
||||||
|
meta l4proto { tcp, udp } iifname $TUN_DEVICE counter accept
|
||||||
|
fib daddr type { local, multicast, broadcast, anycast } counter return
|
||||||
|
ct direction reply counter return
|
||||||
|
ip daddr @reserved_ip counter return
|
||||||
|
ip6 daddr @reserved_ip6 counter return
|
||||||
|
ip daddr @china_ip counter return
|
||||||
|
ip6 daddr @china_ip6 counter return
|
||||||
|
meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return
|
||||||
|
meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return
|
||||||
|
meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return
|
||||||
|
meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter return
|
||||||
|
}
|
||||||
|
|
||||||
|
chain mangle_output {
|
||||||
|
type route hook output priority mangle; policy accept;
|
||||||
|
meta skuid @bypass_user counter return
|
||||||
|
meta skgid @bypass_group counter return
|
||||||
|
fib daddr type { local, multicast, broadcast, anycast } counter return
|
||||||
|
ct direction reply counter return
|
||||||
|
ip daddr @reserved_ip counter return
|
||||||
|
ip6 daddr @reserved_ip6 counter return
|
||||||
|
ip daddr @china_ip counter return
|
||||||
|
ip6 daddr @china_ip6 counter return
|
||||||
|
meta nfproto ipv4 meta l4proto . th dport != @proxy_dport ip daddr != $FAKE_IP counter return
|
||||||
|
meta nfproto ipv6 meta l4proto . th dport != @proxy_dport counter return
|
||||||
|
meta l4proto { tcp, udp } ip dscp == @bypass_dscp ip daddr != $FAKE_IP counter return
|
||||||
|
meta l4proto { tcp, udp } ip6 dscp == @bypass_dscp counter return
|
||||||
|
meta nfproto @dns_hijack_nfproto meta l4proto { tcp, udp } th dport 53 counter return
|
||||||
|
}
|
||||||
|
}
|
19
nikki/files/nftables/reserved_ip.nft
Normal file
19
nikki/files/nftables/reserved_ip.nft
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
|
||||||
|
table inet nikki {
|
||||||
|
set reserved_ip {
|
||||||
|
type ipv4_addr
|
||||||
|
flags interval
|
||||||
|
elements = {
|
||||||
|
0.0.0.0/8,
|
||||||
|
10.0.0.0/8,
|
||||||
|
127.0.0.0/8,
|
||||||
|
100.64.0.0/10,
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
nikki/files/nftables/reserved_ip6.nft
Normal file
23
nikki/files/nftables/reserved_ip6.nft
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/sbin/nft -f
|
||||||
|
|
||||||
|
table inet nikki {
|
||||||
|
set reserved_ip6 {
|
||||||
|
type ipv6_addr
|
||||||
|
flags interval
|
||||||
|
elements = {
|
||||||
|
::/128,
|
||||||
|
::1/128,
|
||||||
|
::ffff:0:0/96,
|
||||||
|
100::/64,
|
||||||
|
64:ff9b::/96,
|
||||||
|
2001::/32,
|
||||||
|
2001:10::/28,
|
||||||
|
2001:20::/28,
|
||||||
|
2001:db8::/32,
|
||||||
|
2002::/16,
|
||||||
|
fc00::/7,
|
||||||
|
fe80::/10,
|
||||||
|
ff00::/8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
199
nikki/files/nikki.conf
Normal file
199
nikki/files/nikki.conf
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
config status 'status'
|
||||||
|
|
||||||
|
config config 'config'
|
||||||
|
option 'init' '1'
|
||||||
|
option 'enabled' '0'
|
||||||
|
option 'profile' 'subscription:subscription'
|
||||||
|
option 'start_delay' '0'
|
||||||
|
option 'scheduled_restart' '0'
|
||||||
|
option 'cron_expression' '0 3 * * *'
|
||||||
|
option 'test_profile' '1'
|
||||||
|
option 'mixin' '1'
|
||||||
|
|
||||||
|
config proxy 'proxy'
|
||||||
|
option 'transparent_proxy' '1'
|
||||||
|
option 'tcp_transparent_proxy_mode' 'redirect'
|
||||||
|
option 'udp_transparent_proxy_mode' 'tun'
|
||||||
|
option 'ipv4_dns_hijack' '1'
|
||||||
|
option 'ipv6_dns_hijack' '1'
|
||||||
|
option 'ipv4_proxy' '1'
|
||||||
|
option 'ipv6_proxy' '0'
|
||||||
|
option 'router_proxy' '1'
|
||||||
|
option 'lan_proxy' '1'
|
||||||
|
option 'access_control_mode' 'all'
|
||||||
|
option 'acl_ip' ''
|
||||||
|
option 'acl_ip6' ''
|
||||||
|
option 'acl_mac' ''
|
||||||
|
option 'acl_interface' ''
|
||||||
|
list 'bypass_user' 'aria2'
|
||||||
|
list 'bypass_user' 'dnsmasq'
|
||||||
|
list 'bypass_user' 'ftp'
|
||||||
|
list 'bypass_user' 'logd'
|
||||||
|
list 'bypass_user' 'nobody'
|
||||||
|
list 'bypass_user' 'ntp'
|
||||||
|
list 'bypass_user' 'ubus'
|
||||||
|
list 'bypass_group' 'aria2'
|
||||||
|
list 'bypass_group' 'dnsmasq'
|
||||||
|
list 'bypass_group' 'ftp'
|
||||||
|
list 'bypass_group' 'logd'
|
||||||
|
list 'bypass_group' 'nogroup'
|
||||||
|
list 'bypass_group' 'ntp'
|
||||||
|
list 'bypass_group' 'ubus'
|
||||||
|
option 'bypass_china_mainland_ip' '0'
|
||||||
|
option 'proxy_tcp_dport' '0-65535'
|
||||||
|
option 'proxy_udp_dport' '0-65535'
|
||||||
|
|
||||||
|
config subscription 'subscription'
|
||||||
|
option 'name' 'default'
|
||||||
|
option 'url' 'http://example.com/default.yaml'
|
||||||
|
option 'user_agent' 'clash'
|
||||||
|
option 'prefer' 'remote'
|
||||||
|
|
||||||
|
config mixin 'mixin'
|
||||||
|
option 'log_level' 'warning'
|
||||||
|
option 'mode' 'rule'
|
||||||
|
option 'match_process' 'off'
|
||||||
|
option 'outbound_interface' ''
|
||||||
|
option 'ipv6' '0'
|
||||||
|
option 'unify_delay' '1'
|
||||||
|
option 'tcp_concurrent' '1'
|
||||||
|
option 'tcp_keep_alive_idle' '600'
|
||||||
|
option 'tcp_keep_alive_interval' '15'
|
||||||
|
option 'ui_name' ''
|
||||||
|
option 'ui_url' 'https://github.com/Zephyruso/zashboard/archive/refs/heads/gh-pages.zip'
|
||||||
|
option 'api_port' '9090'
|
||||||
|
option 'api_secret' ''
|
||||||
|
option 'selection_cache' '1'
|
||||||
|
option 'allow_lan' '1'
|
||||||
|
option 'http_port' '8080'
|
||||||
|
option 'socks_port' '1080'
|
||||||
|
option 'mixed_port' '7890'
|
||||||
|
option 'redir_port' '7891'
|
||||||
|
option 'tproxy_port' '7892'
|
||||||
|
option 'authentication' '1'
|
||||||
|
option 'tun_device' 'nikki'
|
||||||
|
option 'tun_stack' 'system'
|
||||||
|
option 'tun_mtu' '9000'
|
||||||
|
option 'tun_gso' '1'
|
||||||
|
option 'tun_gso_max_size' '65536'
|
||||||
|
option 'tun_dns_hijack' '0'
|
||||||
|
list 'tun_dns_hijacks' 'tcp://any:53'
|
||||||
|
list 'tun_dns_hijacks' 'udp://any:53'
|
||||||
|
option 'tun_endpoint_independent_nat' '0'
|
||||||
|
option 'dns_port' '1053'
|
||||||
|
option 'dns_mode' 'fake-ip'
|
||||||
|
option 'fake_ip_range' '198.18.0.1/16'
|
||||||
|
option 'fake_ip_filter' '0'
|
||||||
|
list 'fake_ip_filters' '+.lan'
|
||||||
|
list 'fake_ip_filters' '+.local'
|
||||||
|
option 'fake_ip_cache' '1'
|
||||||
|
option 'dns_respect_rules' '0'
|
||||||
|
option 'dns_doh_prefer_http3' '0'
|
||||||
|
option 'dns_ipv6' '0'
|
||||||
|
option 'dns_system_hosts' '0'
|
||||||
|
option 'dns_hosts' '1'
|
||||||
|
option 'hosts' '0'
|
||||||
|
option 'dns_nameserver' '0'
|
||||||
|
option 'dns_nameserver_policy' '0'
|
||||||
|
option 'sniffer' '0'
|
||||||
|
option 'sniffer_sniff_dns_mapping' '1'
|
||||||
|
option 'sniffer_sniff_pure_ip' '1'
|
||||||
|
option 'sniffer_overwrite_destination' '0'
|
||||||
|
option 'sniffer_force_domain_name' '0'
|
||||||
|
option 'sniffer_force_domain_names' ''
|
||||||
|
option 'sniffer_ignore_domain_name' '0'
|
||||||
|
option 'sniffer_ignore_domain_names' ''
|
||||||
|
option 'sniffer_sniff' '0'
|
||||||
|
option 'geoip_format' 'dat'
|
||||||
|
option 'geodata_loader' 'memconservative'
|
||||||
|
option 'geosite_url' 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat'
|
||||||
|
option 'geoip_mmdb_url' 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.metadb'
|
||||||
|
option 'geoip_dat_url' 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat'
|
||||||
|
option 'geoip_asn_url' 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/GeoLite2-ASN.mmdb'
|
||||||
|
option 'geox_auto_update' '0'
|
||||||
|
option 'geox_update_interval' '24'
|
||||||
|
option 'mixin_file_content' '0'
|
||||||
|
|
||||||
|
config env 'env'
|
||||||
|
option 'disable_safe_path_check' '0'
|
||||||
|
option 'disable_loopback_detector' '0'
|
||||||
|
option 'disable_quic_go_gso' '0'
|
||||||
|
option 'disable_quic_go_ecn' '0'
|
||||||
|
|
||||||
|
config authentication
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'username' 'nikki'
|
||||||
|
option 'password' ''
|
||||||
|
|
||||||
|
config hosts
|
||||||
|
option 'enabled' '0'
|
||||||
|
option 'domain_name' 'localhost'
|
||||||
|
list 'ip' '127.0.0.1'
|
||||||
|
list 'ip' '::1'
|
||||||
|
|
||||||
|
config nameserver
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'type' 'default-nameserver'
|
||||||
|
list 'nameserver' '223.5.5.5'
|
||||||
|
list 'nameserver' '119.29.29.29'
|
||||||
|
|
||||||
|
config nameserver
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'type' 'proxy-server-nameserver'
|
||||||
|
list 'nameserver' 'https://dns.alidns.com/dns-query'
|
||||||
|
list 'nameserver' 'https://doh.pub/dns-query'
|
||||||
|
|
||||||
|
config nameserver
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'type' 'direct-nameserver'
|
||||||
|
list 'nameserver' 'https://dns.alidns.com/dns-query'
|
||||||
|
list 'nameserver' 'https://doh.pub/dns-query'
|
||||||
|
|
||||||
|
config nameserver
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'type' 'nameserver'
|
||||||
|
list 'nameserver' 'https://dns.alidns.com/dns-query'
|
||||||
|
list 'nameserver' 'https://doh.pub/dns-query'
|
||||||
|
|
||||||
|
config nameserver
|
||||||
|
option 'enabled' '0'
|
||||||
|
option 'type' 'fallback'
|
||||||
|
list 'nameserver' 'https://dns.cloudflare.com/dns-query'
|
||||||
|
list 'nameserver' 'https://dns.google/dns-query'
|
||||||
|
|
||||||
|
config nameserver_policy
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'matcher' 'geosite:cn,private'
|
||||||
|
list 'nameserver' 'https://dns.alidns.com/dns-query'
|
||||||
|
list 'nameserver' 'https://doh.pub/dns-query'
|
||||||
|
|
||||||
|
config nameserver_policy
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'matcher' 'geosite:geolocation-!cn'
|
||||||
|
list 'nameserver' 'https://dns.cloudflare.com/dns-query'
|
||||||
|
list 'nameserver' 'https://dns.google/dns-query'
|
||||||
|
|
||||||
|
config sniff
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'protocol' 'HTTP'
|
||||||
|
list 'port' '80'
|
||||||
|
list 'port' '8080'
|
||||||
|
option 'overwrite_destination' '1'
|
||||||
|
|
||||||
|
config sniff
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'protocol' 'TLS'
|
||||||
|
list 'port' '443'
|
||||||
|
list 'port' '8443'
|
||||||
|
option 'overwrite_destination' '1'
|
||||||
|
|
||||||
|
config sniff
|
||||||
|
option 'enabled' '1'
|
||||||
|
option 'protocol' 'QUIC'
|
||||||
|
list 'port' '443'
|
||||||
|
list 'port' '8443'
|
||||||
|
option 'overwrite_destination' '1'
|
||||||
|
|
||||||
|
config editor 'editor'
|
||||||
|
|
||||||
|
config log 'log'
|
808
nikki/files/nikki.init
Normal file
808
nikki/files/nikki.init
Normal file
@ -0,0 +1,808 @@
|
|||||||
|
#!/bin/sh /etc/rc.common
|
||||||
|
|
||||||
|
START=99
|
||||||
|
STOP=10
|
||||||
|
USE_PROCD=1
|
||||||
|
|
||||||
|
. "$IPKG_INSTROOT/lib/functions/network.sh"
|
||||||
|
. "$IPKG_INSTROOT/etc/nikki/scripts/include.sh"
|
||||||
|
|
||||||
|
extra_command 'update_subscription' 'Update subscription by section id'
|
||||||
|
|
||||||
|
boot() {
|
||||||
|
# prepare files
|
||||||
|
prepare_files
|
||||||
|
# load config
|
||||||
|
config_load nikki
|
||||||
|
# start delay
|
||||||
|
local enabled start_delay
|
||||||
|
config_get_bool enabled "config" "enabled" 0
|
||||||
|
config_get start_delay "config" "start_delay" 0
|
||||||
|
if [[ "$enabled" == 1 && "$start_delay" -gt 0 ]]; then
|
||||||
|
log "App" "Start after $start_delay seconds."
|
||||||
|
sleep "$start_delay"
|
||||||
|
fi
|
||||||
|
# start
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
start_service() {
|
||||||
|
# prepare files
|
||||||
|
prepare_files
|
||||||
|
# load config
|
||||||
|
config_load nikki
|
||||||
|
# check if enabled
|
||||||
|
local enabled
|
||||||
|
config_get_bool enabled "config" "enabled" 0
|
||||||
|
if [ "$enabled" == 0 ]; then
|
||||||
|
log "App" "Disabled."
|
||||||
|
log "App" "Exit."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# start
|
||||||
|
log "App" "Enabled."
|
||||||
|
log "App" "Start."
|
||||||
|
# get config
|
||||||
|
## app config
|
||||||
|
local scheduled_restart cron_expression profile mixin test_profile fast_reload
|
||||||
|
config_get_bool scheduled_restart "config" "scheduled_restart" 0
|
||||||
|
config_get cron_expression "config" "cron_expression"
|
||||||
|
config_get profile "config" "profile"
|
||||||
|
config_get_bool mixin "config" "mixin" 0
|
||||||
|
config_get_bool test_profile "config" "test_profile" 0
|
||||||
|
config_get_bool fast_reload "config" "fast_reload" 0
|
||||||
|
## proxy config
|
||||||
|
### transparent proxy
|
||||||
|
local tcp_transparent_proxy_mode udp_transparent_proxy_mode
|
||||||
|
config_get_bool transparent_proxy "proxy" "transparent_proxy" 0
|
||||||
|
config_get tcp_transparent_proxy_mode "proxy" "tcp_transparent_proxy_mode" "tproxy"
|
||||||
|
config_get udp_transparent_proxy_mode "proxy" "udp_transparent_proxy_mode" "tproxy"
|
||||||
|
## mixin config
|
||||||
|
### general
|
||||||
|
local mode match_process outbound_interface ipv6 unify_delay tcp_concurrent tcp_keep_alive_idle tcp_keep_alive_interval log_level
|
||||||
|
config_get mode "mixin" "mode" "rule"
|
||||||
|
config_get match_process "mixin" "match_process" "off"
|
||||||
|
config_get outbound_interface "mixin" "outbound_interface"
|
||||||
|
config_get_bool ipv6 "mixin" "ipv6" 0
|
||||||
|
config_get_bool unify_delay "mixin" "unify_delay" 0
|
||||||
|
config_get_bool tcp_concurrent "mixin" "tcp_concurrent" 0
|
||||||
|
config_get tcp_keep_alive_idle "mixin" "tcp_keep_alive_idle" 600
|
||||||
|
config_get tcp_keep_alive_interval "mixin" "tcp_keep_alive_interval" 15
|
||||||
|
config_get log_level "mixin" "log_level" "info"
|
||||||
|
### external control
|
||||||
|
local ui_name ui_url api_port api_secret selection_cache
|
||||||
|
config_get ui_name "mixin" "ui_name"
|
||||||
|
config_get ui_url "mixin" "ui_url"
|
||||||
|
config_get api_port "mixin" "api_port" "9090"
|
||||||
|
config_get api_secret "mixin" "api_secret" "666666"
|
||||||
|
config_get_bool selection_cache "mixin" "selection_cache" 0
|
||||||
|
### inbound
|
||||||
|
local allow_lan http_port socks_port mixed_port redir_port tproxy_port authentication
|
||||||
|
config_get_bool allow_lan "mixin" "allow_lan" 0
|
||||||
|
config_get http_port "mixin" "http_port" "8080"
|
||||||
|
config_get socks_port "mixin" "socks_port" "1080"
|
||||||
|
config_get mixed_port "mixin" "mixed_port" "7890"
|
||||||
|
config_get redir_port "mixin" "redir_port" "7891"
|
||||||
|
config_get tproxy_port "mixin" "tproxy_port" "7892"
|
||||||
|
config_get_bool authentication "mixin" "authentication" 0
|
||||||
|
### tun
|
||||||
|
local tun_device tun_stack tun_mtu tun_gso tun_gso_max_size tun_dns_hijack tun_endpoint_independent_nat
|
||||||
|
config_get tun_device "mixin" "tun_device" "nikki"
|
||||||
|
config_get tun_stack "mixin" "tun_stack" "system"
|
||||||
|
config_get tun_mtu "mixin" "tun_mtu" "9000"
|
||||||
|
config_get_bool tun_gso "mixin" "tun_gso" 0
|
||||||
|
config_get tun_gso_max_size "mixin" "tun_gso_max_size" "65536"
|
||||||
|
config_get_bool tun_dns_hijack "mixin" "tun_dns_hijack" 0
|
||||||
|
config_get_bool tun_endpoint_independent_nat "mixin" "tun_endpoint_independent_nat" 0
|
||||||
|
### dns
|
||||||
|
local dns_port dns_mode fake_ip_range fake_ip_filter fake_ip_filter_mode fake_ip_cache dns_respect_rules dns_doh_prefer_http3 dns_ipv6 dns_system_hosts dns_hosts hosts dns_nameserver dns_nameserver_policy
|
||||||
|
config_get dns_port "mixin" "dns_port" "1053"
|
||||||
|
config_get dns_mode "mixin" "dns_mode" "redir-host"
|
||||||
|
config_get fake_ip_range "mixin" "fake_ip_range" "198.18.0.1/16"
|
||||||
|
config_get_bool fake_ip_filter "mixin" "fake_ip_filter" 0
|
||||||
|
config_get fake_ip_filter_mode "mixin" "fake_ip_filter_mode" "blacklist"
|
||||||
|
config_get_bool fake_ip_cache "mixin" "fake_ip_cache" 0
|
||||||
|
config_get_bool dns_respect_rules "mixin" "dns_respect_rules" 0
|
||||||
|
config_get_bool dns_doh_prefer_http3 "mixin" "dns_doh_prefer_http3" 0
|
||||||
|
config_get_bool dns_ipv6 "mixin" "dns_ipv6" 0
|
||||||
|
config_get_bool dns_system_hosts "mixin" "dns_system_hosts" 0
|
||||||
|
config_get_bool dns_hosts "mixin" "dns_hosts" 0
|
||||||
|
config_get_bool hosts "mixin" "hosts" 0
|
||||||
|
config_get_bool dns_nameserver "mixin" "dns_nameserver" 0
|
||||||
|
config_get_bool dns_nameserver_policy "mixin" "dns_nameserver_policy" 0
|
||||||
|
### sniffer
|
||||||
|
local sniffer sniffer_sniff_dns_mapping sniffer_sniff_pure_ip sniffer_overwrite_destination sniffer_force_domain_name sniffer_ignore_domain_name sniffer_sniff
|
||||||
|
config_get_bool sniffer "mixin" sniffer 0
|
||||||
|
config_get_bool sniffer_sniff_dns_mapping "mixin" sniffer_sniff_dns_mapping 0
|
||||||
|
config_get_bool sniffer_sniff_pure_ip "mixin" sniffer_sniff_pure_ip 0
|
||||||
|
config_get_bool sniffer_overwrite_destination "mixin" sniffer_overwrite_destination 0
|
||||||
|
config_get_bool sniffer_force_domain_name "mixin" sniffer_force_domain_name 0
|
||||||
|
config_get_bool sniffer_ignore_domain_name "mixin" sniffer_ignore_domain_name 0
|
||||||
|
config_get_bool sniffer_sniff "mixin" sniffer_sniff 0
|
||||||
|
### geox
|
||||||
|
local geoip_format geodata_loader geosite_url geoip_mmdb_url geoip_dat_url geoip_asn_url geox_auto_update geox_update_interval
|
||||||
|
config_get geoip_format "mixin" "geoip_format" "mmdb"
|
||||||
|
config_get geodata_loader "mixin" "geodata_loader" "memconservative"
|
||||||
|
config_get geosite_url "mixin" "geosite_url"
|
||||||
|
config_get geoip_mmdb_url "mixin" "geoip_mmdb_url"
|
||||||
|
config_get geoip_dat_url "mixin" "geoip_dat_url"
|
||||||
|
config_get geoip_asn_url "mixin" "geoip_asn_url"
|
||||||
|
config_get_bool geox_auto_update "mixin" "geox_auto_update" 0
|
||||||
|
config_get geox_update_interval "mixin" "geox_update_interval" "24"
|
||||||
|
### mixin file content
|
||||||
|
local mixin_file_content
|
||||||
|
config_get_bool mixin_file_content "mixin" "mixin_file_content" 0
|
||||||
|
## environment variable
|
||||||
|
local disable_safe_path_check disable_loopback_detector disable_quic_go_gso disable_quic_go_ecn
|
||||||
|
config_get_bool disable_safe_path_check "env" "disable_safe_path_check" 0
|
||||||
|
config_get_bool disable_loopback_detector "env" "disable_loopback_detector" 0
|
||||||
|
config_get_bool disable_quic_go_gso "env" "disable_quic_go_gso" 0
|
||||||
|
config_get_bool disable_quic_go_ecn "env" "disable_quic_go_ecn" 0
|
||||||
|
# prepare
|
||||||
|
local tproxy_enable; tproxy_enable=0
|
||||||
|
if [[ "$tcp_transparent_proxy_mode" == "tproxy" || "$udp_transparent_proxy_mode" == "tproxy" ]]; then
|
||||||
|
tproxy_enable=1
|
||||||
|
fi
|
||||||
|
local tun_enable; tun_enable=0
|
||||||
|
if [[ "$tcp_transparent_proxy_mode" == "tun" || "$udp_transparent_proxy_mode" == "tun" ]]; then
|
||||||
|
tun_enable=1
|
||||||
|
fi
|
||||||
|
# get profile
|
||||||
|
if [[ "$profile" == "file:"* ]]; then
|
||||||
|
local profile_name; profile_name=$(basename "${profile/file:/}")
|
||||||
|
local profile_file; profile_file="$PROFILES_DIR/$profile_name"
|
||||||
|
log "Profile" "Use file: $profile_name."
|
||||||
|
if [ ! -f "$profile_file" ]; then
|
||||||
|
log "Profile" "File not found."
|
||||||
|
log "App" "Exit."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
cp -f "$profile_file" "$RUN_PROFILE_PATH"
|
||||||
|
elif [[ "$profile" == "subscription:"* ]]; then
|
||||||
|
local subscription_section; subscription_section="${profile/subscription:/}"
|
||||||
|
local subscription_name subscription_prefer
|
||||||
|
config_get subscription_name "$subscription_section" "name"
|
||||||
|
config_get subscription_prefer "$subscription_section" "prefer" "remote"
|
||||||
|
log "Profile" "Use subscription: $subscription_name."
|
||||||
|
local subscription_file; subscription_file="$SUBSCRIPTIONS_DIR/$subscription_section.yaml"
|
||||||
|
if [ "$subscription_prefer" == "remote" ] || [[ "$subscription_prefer" == "local" && ! -f "$subscription_file" ]]; then
|
||||||
|
update_subscription "$subscription_section"
|
||||||
|
fi
|
||||||
|
if [ ! -f "$subscription_file" ]; then
|
||||||
|
log "Profile" "Subscription file not found."
|
||||||
|
log "App" "Exit."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
cp -f "$subscription_file" "$RUN_PROFILE_PATH"
|
||||||
|
else
|
||||||
|
log "Profile" "No profile/subscription selected."
|
||||||
|
log "App" "Exit."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# mixin
|
||||||
|
if [ "$mixin" == 0 ]; then
|
||||||
|
log "Mixin" "Disabled."
|
||||||
|
log "Mixin" "Mixin neccesary config."
|
||||||
|
# do mixin
|
||||||
|
log_level="$log_level" mode="$mode" match_process="$match_process" ipv6="$ipv6" \
|
||||||
|
ui_path="ui" ui_name="$ui_name" ui_url="$ui_url" api_listen="0.0.0.0:$api_port" api_secret="$api_secret" \
|
||||||
|
allow_lan="$allow_lan" http_port="$http_port" socks_port="$socks_port" mixed_port="$mixed_port" redir_port="$redir_port" tproxy_port="$tproxy_port" \
|
||||||
|
tun_enable="$tun_enable" tun_stack="$tun_stack" tun_device="$tun_device" tun_mtu="$tun_mtu" tun_gso="$tun_gso" tun_gso_max_size="$tun_gso_max_size" tun_endpoint_independent_nat="$tun_endpoint_independent_nat" \
|
||||||
|
dns_enable="true" dns_listen="0.0.0.0:$dns_port" dns_mode="$dns_mode" fake_ip_range="$fake_ip_range" \
|
||||||
|
yq -M -i '
|
||||||
|
.log-level = strenv(log_level) | .mode = strenv(mode) | .find-process-mode = strenv(match_process) | .ipv6 = env(ipv6) == 1 |
|
||||||
|
.external-ui = strenv(ui_path) | .external-ui-name = strenv(ui_name) | .external-ui-url = strenv(ui_url) | .external-controller = strenv(api_listen) | .secret = strenv(api_secret) |
|
||||||
|
.allow-lan = env(allow_lan) == 1 | .port = env(http_port) | .socks-port = env(socks_port) | .mixed-port = env(mixed_port) | .redir-port = env(redir_port) | .tproxy-port = env(tproxy_port) |
|
||||||
|
.tun.enable = env(tun_enable) == 1 | .tun.stack = strenv(tun_stack) | .tun.device = strenv(tun_device) | .tun.mtu = env(tun_mtu) | .tun.gso = env(tun_gso) == 1 | .tun.gso-max-size = env(tun_gso_max_size) | .tun.endpoint-independent-nat = env(tun_endpoint_independent_nat) == 1 |
|
||||||
|
.tun.auto-route = false | .tun.auto-redirect = false | .tun.auto-detect-interface = false |
|
||||||
|
.dns.enable = env(dns_enable) | .dns.listen = strenv(dns_listen) | .dns.enhanced-mode = strenv(dns_mode) | .dns.fake-ip-range = strenv(fake_ip_range)
|
||||||
|
' "$RUN_PROFILE_PATH"
|
||||||
|
else
|
||||||
|
log "Mixin" "Enabled."
|
||||||
|
log "Mixin" "Mixin all config."
|
||||||
|
# do mixin
|
||||||
|
log_level="$log_level" mode="$mode" match_process="$match_process" ipv6="$ipv6" unify_delay="$unify_delay" tcp_concurrent="$tcp_concurrent" tcp_keep_alive_idle="$tcp_keep_alive_idle" tcp_keep_alive_interval="$tcp_keep_alive_interval" \
|
||||||
|
ui_path="ui" ui_name="$ui_name" ui_url="$ui_url" api_listen="0.0.0.0:$api_port" api_secret="$api_secret" selection_cache="$selection_cache" \
|
||||||
|
allow_lan="$allow_lan" http_port="$http_port" socks_port="$socks_port" mixed_port="$mixed_port" redir_port="$redir_port" tproxy_port="$tproxy_port" \
|
||||||
|
tun_enable="$tun_enable" tun_stack="$tun_stack" tun_device="$tun_device" tun_mtu="$tun_mtu" tun_gso="$tun_gso" tun_gso_max_size="$tun_gso_max_size" tun_endpoint_independent_nat="$tun_endpoint_independent_nat" \
|
||||||
|
dns_enable="true" dns_listen="0.0.0.0:$dns_port" dns_mode="$dns_mode" fake_ip_range="$fake_ip_range" fake_ip_cache="$fake_ip_cache" \
|
||||||
|
dns_respect_rules="$dns_respect_rules" dns_doh_prefer_http3="$dns_doh_prefer_http3" dns_ipv6="$dns_ipv6" dns_system_hosts="$dns_system_hosts" dns_hosts="$dns_hosts" \
|
||||||
|
sniffer="$sniffer" sniffer_sniff_dns_mapping="$sniffer_sniff_dns_mapping" sniffer_sniff_pure_ip="$sniffer_sniff_pure_ip" sniffer_overwrite_destination="$sniffer_overwrite_destination" \
|
||||||
|
geoip_format="$geoip_format" geodata_loader="$geodata_loader" geosite_url="$geosite_url" geoip_mmdb_url="$geoip_mmdb_url" geoip_dat_url="$geoip_dat_url" geoip_asn_url="$geoip_asn_url" \
|
||||||
|
geox_auto_update="$geox_auto_update" geox_update_interval="$geox_update_interval" \
|
||||||
|
yq -M -i '
|
||||||
|
.log-level = strenv(log_level) | .mode = strenv(mode) | .find-process-mode = strenv(match_process) | .ipv6 = env(ipv6) == 1 | .unified-delay = env(unify_delay) == 1 | .tcp-concurrent = env(tcp_concurrent) == 1 | .keep-alive-idle = env(tcp_keep_alive_idle) | .keep-alive-interval = env(tcp_keep_alive_interval) |
|
||||||
|
.external-ui = strenv(ui_path) | .external-ui-name = strenv(ui_name) | .external-ui-url = strenv(ui_url) | .external-controller = strenv(api_listen) | .secret = strenv(api_secret) | .profile.store-selected = env(selection_cache) == 1 |
|
||||||
|
.allow-lan = env(allow_lan) == 1 | .port = env(http_port) | .socks-port = env(socks_port) | .mixed-port = env(mixed_port) | .redir-port = env(redir_port) | .tproxy-port = env(tproxy_port) |
|
||||||
|
.tun.enable = env(tun_enable) == 1 | .tun.stack = strenv(tun_stack) | .tun.device = strenv(tun_device) | .tun.mtu = env(tun_mtu) | .tun.gso = env(tun_gso) == 1 | .tun.gso-max-size = env(tun_gso_max_size) | .tun.endpoint-independent-nat = env(tun_endpoint_independent_nat) == 1 |
|
||||||
|
.tun.auto-route = false | .tun.auto-redirect = false | .tun.auto-detect-interface = false |
|
||||||
|
.dns.enable = env(dns_enable) | .dns.listen = strenv(dns_listen) | .dns.enhanced-mode = strenv(dns_mode) | .dns.fake-ip-range = strenv(fake_ip_range) | .profile.store-fake-ip = env(fake_ip_cache) == 1 |
|
||||||
|
.dns.respect-rules = env(dns_respect_rules) == 1 | .dns.prefer-h3 = env(dns_doh_prefer_http3) == 1 | .dns.ipv6 = env(dns_ipv6) == 1 | .dns.use-system-hosts = env(dns_system_hosts) == 1 | .dns.use-hosts = env(dns_hosts) == 1 |
|
||||||
|
.sniffer.enable = env(sniffer) == 1 | .sniffer.force-dns-mapping = env(sniffer_sniff_dns_mapping) == 1 | .sniffer.parse-pure-ip = env(sniffer_sniff_pure_ip) == 1 | .sniffer.override-destination = env(sniffer_overwrite_destination) == 1 |
|
||||||
|
.geodata-mode = strenv(geoip_format) == "dat" | .geodata-loader = strenv(geodata_loader) | .geox-url.geosite = strenv(geosite_url) | .geox-url.mmdb = strenv(geoip_mmdb_url) | .geox-url.geoip = strenv(geoip_dat_url) | .geox-url.asn = strenv(geoip_asn_url) |
|
||||||
|
.geo-auto-update = env(geox_auto_update) == 1 | .geo-update-interval = env(geox_update_interval)
|
||||||
|
' "$RUN_PROFILE_PATH"
|
||||||
|
|
||||||
|
if [ "$fake_ip_filter" == 1 ]; then
|
||||||
|
fake_ip_filter_mode="$fake_ip_filter_mode" \
|
||||||
|
yq -M -i 'del(.dns.fake-ip-filter) | .dns.fake-ip-filter-mode = strenv(fake_ip_filter_mode)' "$RUN_PROFILE_PATH"
|
||||||
|
config_list_foreach "mixin" "fake_ip_filters" mixin_fake_ip_filters
|
||||||
|
fi
|
||||||
|
if [ "$hosts" == 1 ]; then
|
||||||
|
yq -M -i 'del(.hosts)' "$RUN_PROFILE_PATH"
|
||||||
|
config_foreach mixin_hosts "hosts"
|
||||||
|
fi
|
||||||
|
if [ "$dns_nameserver" == 1 ]; then
|
||||||
|
yq -M -i 'del(.dns.default-nameserver) | del(.dns.proxy-server-nameserver) | del(.dns.direct-nameserver) | del(.dns.nameserver) | del(.dns.fallback)' "$RUN_PROFILE_PATH"
|
||||||
|
config_foreach mixin_nameservers "nameserver"
|
||||||
|
fi
|
||||||
|
if [ "$dns_nameserver_policy" == 1 ]; then
|
||||||
|
yq -M -i 'del(.dns.nameserver-policy)' "$RUN_PROFILE_PATH"
|
||||||
|
config_foreach mixin_nameserver_policies "nameserver_policy"
|
||||||
|
fi
|
||||||
|
if [ "$sniffer_force_domain_name" == 1 ]; then
|
||||||
|
yq -M -i 'del(.sniffer.force-domain)' "$RUN_PROFILE_PATH"
|
||||||
|
config_list_foreach "mixin" "sniffer_force_domain_names" mixin_sniffer_domain_names "force-domain"
|
||||||
|
fi
|
||||||
|
if [ "$sniffer_ignore_domain_name" == 1 ]; then
|
||||||
|
yq -M -i 'del(.sniffer.skip-domain)' "$RUN_PROFILE_PATH"
|
||||||
|
config_list_foreach "mixin" "sniffer_ignore_domain_names" mixin_sniffer_domain_names "skip-domain"
|
||||||
|
fi
|
||||||
|
if [ "$sniffer_sniff" == 1 ]; then
|
||||||
|
yq -M -i 'del(.sniffer.sniff)' "$RUN_PROFILE_PATH"
|
||||||
|
config_foreach mixin_sniffs "sniff"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
yq -M -i 'del (.bind-address)' "$RUN_PROFILE_PATH"
|
||||||
|
if [ -n "$outbound_interface" ]; then
|
||||||
|
local outbound_device; network_get_device outbound_device "$outbound_interface"
|
||||||
|
if [ -n "$outbound_device" ]; then
|
||||||
|
outbound_device="$outbound_device" yq -M -i '.interface-name = strenv(outbound_device)' "$RUN_PROFILE_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$authentication" == 1 ]; then
|
||||||
|
yq -M -i 'del(.authentication)' "$RUN_PROFILE_PATH"
|
||||||
|
config_foreach mixin_authentications "authentication"
|
||||||
|
fi
|
||||||
|
if [ "$tun_dns_hijack" == 1 ]; then
|
||||||
|
config_list_foreach "mixin" "tun_dns_hijacks" mixin_tun_dns_hijacks
|
||||||
|
fi
|
||||||
|
if [ "$mixin_file_content" == 1 ]; then
|
||||||
|
if [ -s "$MIXIN_FILE_PATH" ]; then
|
||||||
|
yq -M -i ea '. as $item ireduce ({}; . * $item ) | ... comments=""' "$RUN_PROFILE_PATH" "$MIXIN_FILE_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# test profile
|
||||||
|
if [ "$test_profile" == 1 ]; then
|
||||||
|
log "Profile" "Testing..."
|
||||||
|
if ($PROG -d "$RUN_DIR" -t >> "$CORE_LOG_PATH" 2>&1); then
|
||||||
|
log "Profile" "Test passed!"
|
||||||
|
else
|
||||||
|
log "Profile" "Test failed!"
|
||||||
|
log "Profile" "Please check the core log to find out the problem."
|
||||||
|
log "App" "Exit."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# start core
|
||||||
|
log "Core" "Start."
|
||||||
|
procd_open_instance nikki
|
||||||
|
|
||||||
|
procd_set_param command /bin/sh -c "$PROG -d $RUN_DIR >> $CORE_LOG_PATH 2>&1"
|
||||||
|
procd_set_param file "$RUN_PROFILE_PATH"
|
||||||
|
procd_set_param env SKIP_SAFE_PATH_CHECK="$disable_safe_path_check" DISABLE_LOOPBACK_DETECTOR="$disable_loopback_detector" QUIC_GO_DISABLE_GSO="$disable_quic_go_gso" QUIC_GO_DISABLE_ECN="$disable_quic_go_ecn"
|
||||||
|
if [ "$fast_reload" == 1 ]; then
|
||||||
|
procd_set_param reload_signal HUP
|
||||||
|
fi
|
||||||
|
procd_set_param respawn
|
||||||
|
procd_set_param user "$NIKKI_USER"
|
||||||
|
procd_set_param group "$NIKKI_GROUP"
|
||||||
|
|
||||||
|
procd_set_param limits core="unlimited" nofile="1048576 1048576"
|
||||||
|
|
||||||
|
procd_close_instance
|
||||||
|
# cron
|
||||||
|
if [[ "$scheduled_restart" == 1 && -n "$cron_expression" ]]; then
|
||||||
|
log "App" "Set scheduled restart."
|
||||||
|
echo "$cron_expression /etc/init.d/nikki restart #nikki" >> "/etc/crontabs/root"
|
||||||
|
/etc/init.d/cron restart
|
||||||
|
fi
|
||||||
|
# set started flag
|
||||||
|
touch "$STARTED_FLAG"
|
||||||
|
}
|
||||||
|
|
||||||
|
service_started() {
|
||||||
|
# check if started
|
||||||
|
if [ ! -f "$STARTED_FLAG" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# load config
|
||||||
|
config_load nikki
|
||||||
|
# check if transparent proxy enabled
|
||||||
|
local transparent_proxy
|
||||||
|
config_get_bool transparent_proxy "proxy" "transparent_proxy" 0
|
||||||
|
if [ "$transparent_proxy" == 0 ]; then
|
||||||
|
log "Transparent Proxy" "Disabled."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# get config
|
||||||
|
### inbound
|
||||||
|
local http_port socks_port mixed_port redir_port tproxy_port
|
||||||
|
config_get http_port "mixin" "http_port" "8080"
|
||||||
|
config_get socks_port "mixin" "socks_port" "1080"
|
||||||
|
config_get mixed_port "mixin" "mixed_port" "7890"
|
||||||
|
config_get redir_port "mixin" "redir_port" "7891"
|
||||||
|
config_get tproxy_port "mixin" "tproxy_port" "7892"
|
||||||
|
### dns
|
||||||
|
local dns_port fake_ip_range
|
||||||
|
config_get dns_port "mixin" "dns_port" "1053"
|
||||||
|
config_get fake_ip_range "mixin" "fake_ip_range" "198.18.0.1/16"
|
||||||
|
### tun
|
||||||
|
local tun_device
|
||||||
|
config_get tun_device "mixin" "tun_device" "nikki"
|
||||||
|
## proxy config
|
||||||
|
### transparent proxy
|
||||||
|
local tcp_transparent_proxy_mode udp_transparent_proxy_mode ipv4_dns_hijack ipv6_dns_hijack ipv4_proxy ipv6_proxy router_proxy lan_proxy
|
||||||
|
config_get tcp_transparent_proxy_mode "proxy" "tcp_transparent_proxy_mode" "redirect"
|
||||||
|
config_get udp_transparent_proxy_mode "proxy" "udp_transparent_proxy_mode" "tun"
|
||||||
|
config_get_bool ipv4_dns_hijack "proxy" "ipv4_dns_hijack" 0
|
||||||
|
config_get_bool ipv6_dns_hijack "proxy" "ipv6_dns_hijack" 0
|
||||||
|
config_get_bool ipv4_proxy "proxy" "ipv4_proxy" 0
|
||||||
|
config_get_bool ipv6_proxy "proxy" "ipv6_proxy" 0
|
||||||
|
config_get_bool router_proxy "proxy" "router_proxy" 0
|
||||||
|
config_get_bool lan_proxy "proxy" "lan_proxy" 0
|
||||||
|
### access control
|
||||||
|
local access_control_mode bypass_china_mainland_ip proxy_tcp_dport proxy_udp_dport bypass_dscp
|
||||||
|
config_get access_control_mode "proxy" "access_control_mode"
|
||||||
|
config_get_bool bypass_china_mainland_ip "proxy" "bypass_china_mainland_ip" 0
|
||||||
|
config_get proxy_tcp_dport "proxy" "proxy_tcp_dport" "0-65535"
|
||||||
|
config_get proxy_udp_dport "proxy" "proxy_udp_dport" "0-65535"
|
||||||
|
config_get bypass_dscp "proxy" "bypass_dscp"
|
||||||
|
# prepare
|
||||||
|
local tproxy_enable; tproxy_enable=0
|
||||||
|
if [[ "$tcp_transparent_proxy_mode" == "tproxy" || "$udp_transparent_proxy_mode" == "tproxy" ]]; then
|
||||||
|
tproxy_enable=1
|
||||||
|
fi
|
||||||
|
local tun_enable; tun_enable=0
|
||||||
|
if [[ "$tcp_transparent_proxy_mode" == "tun" || "$udp_transparent_proxy_mode" == "tun" ]]; then
|
||||||
|
tun_enable=1
|
||||||
|
fi
|
||||||
|
# transparent proxy
|
||||||
|
log "Transparent Proxy" "Enabled."
|
||||||
|
log "Transparent Proxy" "TCP Mode: $tcp_transparent_proxy_mode."
|
||||||
|
log "Transparent Proxy" "UDP Mode: $udp_transparent_proxy_mode."
|
||||||
|
# wait for tun device online
|
||||||
|
if [ "$tun_enable" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Waiting for tun device online..."
|
||||||
|
local tun_timeout; tun_timeout=60
|
||||||
|
local tun_interval; tun_interval=1
|
||||||
|
while [ "$tun_timeout" -gt 0 ]; do
|
||||||
|
if (ip link show dev "$tun_device" > /dev/null 2>&1); then
|
||||||
|
if [ $(ip -json addr show dev "$tun_device" | tun_device="$tun_device" yq -M '.[] | select(.ifname = strenv(tun_device)) | .addr_info | length') -gt 0 ]; then
|
||||||
|
log "Transparent Proxy" "Tun device is online."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
tun_timeout=$((tun_timeout - tun_interval))
|
||||||
|
sleep "$tun_interval"
|
||||||
|
done
|
||||||
|
if [ "$tun_timeout" -le 0 ]; then
|
||||||
|
log "Transparent Proxy" "Waiting timeout, tun device is not online."
|
||||||
|
log "App" "Exit."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# prepare
|
||||||
|
if [ "$tproxy_enable" == 1 ]; then
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
ip -4 route add local default dev lo table "$TPROXY_ROUTE_TABLE"
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
ip -6 route add local default dev lo table "$TPROXY_ROUTE_TABLE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$tun_enable" == 1 ]; then
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
ip -4 route add unicast default dev "$tun_device" table "$TUN_ROUTE_TABLE"
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
ip -6 route add unicast default dev "$tun_device" table "$TUN_ROUTE_TABLE"
|
||||||
|
fi
|
||||||
|
$FIREWALL_INCLUDE_SH
|
||||||
|
fi
|
||||||
|
local tcp_route_table
|
||||||
|
if [ "$tcp_transparent_proxy_mode" == "tproxy" ]; then
|
||||||
|
tcp_route_table="$TPROXY_ROUTE_TABLE"
|
||||||
|
elif [ "$tcp_transparent_proxy_mode" == "tun" ]; then
|
||||||
|
tcp_route_table="$TUN_ROUTE_TABLE"
|
||||||
|
fi
|
||||||
|
if [ -n "$tcp_route_table" ]; then
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
ip -4 rule add pref "$TCP_RULE_PREF" fwmark "$FW_MARK/$FW_MARK_MASK" ipproto tcp table "$tcp_route_table"
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
ip -6 rule add pref "$TCP_RULE_PREF" fwmark "$FW_MARK/$FW_MARK_MASK" ipproto tcp table "$tcp_route_table"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
local udp_route_table
|
||||||
|
if [ "$udp_transparent_proxy_mode" == "tproxy" ]; then
|
||||||
|
udp_route_table="$TPROXY_ROUTE_TABLE"
|
||||||
|
elif [ "$udp_transparent_proxy_mode" == "tun" ]; then
|
||||||
|
udp_route_table="$TUN_ROUTE_TABLE"
|
||||||
|
fi
|
||||||
|
if [ -n "$udp_route_table" ]; then
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
ip -4 rule add pref "$UDP_RULE_PREF" fwmark "$FW_MARK/$FW_MARK_MASK" ipproto udp table "$udp_route_table"
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
ip -6 rule add pref "$UDP_RULE_PREF" fwmark "$FW_MARK/$FW_MARK_MASK" ipproto udp table "$udp_route_table"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
nft -f "$HIJACK_NFT" -D NIKKI_GROUP="$NIKKI_GROUP" -D FW_MARK="$FW_MARK" -D FW_MARK_MASK="$FW_MARK_MASK" -D TUN_DEVICE="$tun_device" -D FAKE_IP="$fake_ip_range" -D DNS_PORT="$dns_port" -D REDIR_PORT="$redir_port" -D TPROXY_PORT="$tproxy_port"
|
||||||
|
nft -f "$RESERVED_IP_NFT"
|
||||||
|
nft -f "$RESERVED_IP6_NFT"
|
||||||
|
# dns hijack
|
||||||
|
if [ "$ipv4_dns_hijack" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Hijack IPv4 dns request."
|
||||||
|
nft add element inet "$FW_TABLE" dns_hijack_nfproto \{ ipv4 \}
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_dns_hijack" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Hijack IPv6 dns request."
|
||||||
|
nft add element inet "$FW_TABLE" dns_hijack_nfproto \{ ipv6 \}
|
||||||
|
fi
|
||||||
|
# proxy
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Proxy IPv4 traffic."
|
||||||
|
nft add element inet "$FW_TABLE" proxy_nfproto \{ ipv4 \}
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Proxy IPv6 traffic."
|
||||||
|
nft add element inet "$FW_TABLE" proxy_nfproto \{ ipv6 \}
|
||||||
|
fi
|
||||||
|
# bypass
|
||||||
|
config_list_foreach "proxy" "bypass_user" add_bypass_user
|
||||||
|
config_list_foreach "proxy" "bypass_group" add_bypass_group
|
||||||
|
if [ "$bypass_china_mainland_ip" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Bypass china mainland ip."
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
nft -f "$GEOIP_CN_NFT"
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
nft -f "$GEOIP6_CN_NFT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
log "Transparent Proxy" "Destination TCP Port to Proxy: $proxy_tcp_dport."
|
||||||
|
log "Transparent Proxy" "Destination UDP Port to Proxy: $proxy_udp_dport."
|
||||||
|
local proxy_dport
|
||||||
|
for proxy_dport in $proxy_tcp_dport; do
|
||||||
|
nft add element inet "$FW_TABLE" proxy_dport \{ "tcp" . "$proxy_dport" \}
|
||||||
|
done
|
||||||
|
for proxy_dport in $proxy_udp_dport; do
|
||||||
|
nft add element inet "$FW_TABLE" proxy_dport \{ "udp" . "$proxy_dport" \}
|
||||||
|
done
|
||||||
|
if [ -n "$bypass_dscp" ]; then
|
||||||
|
log "Transparent Proxy" "Bypass DSCP: $bypass_dscp."
|
||||||
|
local dscp
|
||||||
|
for dscp in $bypass_dscp; do
|
||||||
|
nft add element inet "$FW_TABLE" bypass_dscp \{ "$dscp" \}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
# router proxy
|
||||||
|
if [ "$router_proxy" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Set proxy for router."
|
||||||
|
if [ "$tcp_transparent_proxy_mode" == "redirect" ]; then
|
||||||
|
nft insert rule inet "$FW_TABLE" nat_output jump router_dns_hijack
|
||||||
|
nft add rule inet "$FW_TABLE" nat_output meta l4proto tcp jump "router_${tcp_transparent_proxy_mode}"
|
||||||
|
else
|
||||||
|
nft flush chain inet "$FW_TABLE" nat_output
|
||||||
|
nft add rule inet "$FW_TABLE" nat_output jump router_dns_hijack
|
||||||
|
nft add rule inet "$FW_TABLE" mangle_output meta l4proto tcp jump "router_${tcp_transparent_proxy_mode}"
|
||||||
|
fi
|
||||||
|
nft add rule inet "$FW_TABLE" mangle_output meta l4proto udp jump "router_${udp_transparent_proxy_mode}"
|
||||||
|
fi
|
||||||
|
# lan proxy
|
||||||
|
if [ "$lan_proxy" == 1 ]; then
|
||||||
|
log "Transparent Proxy" "Set proxy for lan."
|
||||||
|
# access control
|
||||||
|
if [ "$access_control_mode" == "all" ]; then
|
||||||
|
log "Transparent Proxy" "Access Control is using all mode, set proxy for all client."
|
||||||
|
elif [ "$access_control_mode" == "allow" ]; then
|
||||||
|
log "Transparent Proxy" "Access Control is using allow mode, set proxy for client which is in acl."
|
||||||
|
elif [ "$access_control_mode" == "block" ]; then
|
||||||
|
log "Transparent Proxy" "Access Control is using block mode, set proxy for client which is not in acl."
|
||||||
|
fi
|
||||||
|
config_list_foreach "proxy" "acl_ip" add_acl_ip
|
||||||
|
config_list_foreach "proxy" "acl_ip6" add_acl_ip6
|
||||||
|
config_list_foreach "proxy" "acl_mac" add_acl_mac
|
||||||
|
config_list_foreach "proxy" "acl_interface" add_acl_interface
|
||||||
|
if [ "$tcp_transparent_proxy_mode" == "redirect" ]; then
|
||||||
|
nft insert rule inet "$FW_TABLE" dstnat jump "${access_control_mode}_dns_hijack"
|
||||||
|
nft add rule inet "$FW_TABLE" dstnat meta l4proto tcp jump "${access_control_mode}_${tcp_transparent_proxy_mode}"
|
||||||
|
else
|
||||||
|
nft flush chain inet "$FW_TABLE" dstnat
|
||||||
|
nft add rule inet "$FW_TABLE" dstnat jump "${access_control_mode}_dns_hijack"
|
||||||
|
nft add rule inet "$FW_TABLE" mangle_prerouting meta l4proto tcp jump "${access_control_mode}_${tcp_transparent_proxy_mode}"
|
||||||
|
fi
|
||||||
|
nft add rule inet "$FW_TABLE" mangle_prerouting meta l4proto udp jump "${access_control_mode}_${udp_transparent_proxy_mode}"
|
||||||
|
fi
|
||||||
|
# fix compatible between tproxy and dockerd (kmod-br-netfilter)
|
||||||
|
if [ "$tproxy_enable" == 1 ] && (lsmod | grep -q br_netfilter); then
|
||||||
|
if [ "$ipv4_proxy" == 1 ]; then
|
||||||
|
local bridge_nf_call_iptables; bridge_nf_call_iptables=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
|
||||||
|
if [ "$bridge_nf_call_iptables" == 1 ]; then
|
||||||
|
touch "$BRIDGE_NF_CALL_IPTABLES_FLAG"
|
||||||
|
sysctl -q -w net.bridge.bridge-nf-call-iptables=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$ipv6_proxy" == 1 ]; then
|
||||||
|
local bridge_nf_call_ip6tables; bridge_nf_call_ip6tables=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
|
||||||
|
if [ "$bridge_nf_call_ip6tables" == 1 ]; then
|
||||||
|
touch "$BRIDGE_NF_CALL_IP6TABLES_FLAG"
|
||||||
|
sysctl -q -w net.bridge.bridge-nf-call-ip6tables=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
service_stopped() {
|
||||||
|
cleanup
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_service() {
|
||||||
|
cleanup
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
service_triggers() {
|
||||||
|
procd_add_reload_trigger "nikki"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
# clear log
|
||||||
|
clear_log
|
||||||
|
# delete routing policy
|
||||||
|
ip -4 rule del ipproto tcp table "$TPROXY_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -4 rule del ipproto udp table "$TPROXY_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -4 rule del ipproto tcp table "$TUN_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -4 rule del ipproto udp table "$TUN_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -6 rule del ipproto tcp table "$TPROXY_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -6 rule del ipproto udp table "$TPROXY_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -6 rule del ipproto tcp table "$TUN_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -6 rule del ipproto udp table "$TUN_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
# delete routing table
|
||||||
|
ip -4 route flush table "$TPROXY_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -4 route flush table "$TUN_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -6 route flush table "$TPROXY_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
ip -6 route flush table "$TUN_ROUTE_TABLE" > /dev/null 2>&1
|
||||||
|
# delete hijack
|
||||||
|
nft delete table inet "$FW_TABLE" > /dev/null 2>&1
|
||||||
|
local handles handle
|
||||||
|
handles=$(nft --json list table inet fw4 | yq -M '.nftables[] | select(has("rule")) | .rule | select(.chain == "input" and .comment == "nikki") | .handle')
|
||||||
|
for handle in $handles; do
|
||||||
|
nft delete rule inet fw4 input handle "$handle"
|
||||||
|
done
|
||||||
|
handles=$(nft --json list table inet fw4 | yq -M '.nftables[] | select(has("rule")) | .rule | select(.chain == "forward" and .comment == "nikki") | .handle')
|
||||||
|
for handle in $handles; do
|
||||||
|
nft delete rule inet fw4 forward handle "$handle"
|
||||||
|
done
|
||||||
|
# delete started flag
|
||||||
|
rm -f "$STARTED_FLAG"
|
||||||
|
# revert fix compatible between tproxy and dockerd (kmod-br-netfilter)
|
||||||
|
if [ -f "$BRIDGE_NF_CALL_IPTABLES_FLAG" ]; then
|
||||||
|
rm -f "$BRIDGE_NF_CALL_IPTABLES_FLAG"
|
||||||
|
sysctl -q -w net.bridge.bridge-nf-call-iptables=1
|
||||||
|
fi
|
||||||
|
if [ -f "$BRIDGE_NF_CALL_IP6TABLES_FLAG" ]; then
|
||||||
|
rm -f "$BRIDGE_NF_CALL_IP6TABLES_FLAG"
|
||||||
|
sysctl -q -w net.bridge.bridge-nf-call-ip6tables=1
|
||||||
|
fi
|
||||||
|
# delete cron
|
||||||
|
sed -i "/#nikki/d" "/etc/crontabs/root" > /dev/null 2>&1
|
||||||
|
/etc/init.d/cron restart
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_authentications() {
|
||||||
|
local section="$1"
|
||||||
|
|
||||||
|
local enabled username password
|
||||||
|
config_get_bool enabled "$section" "enabled" 0
|
||||||
|
config_get username "$section" "username"
|
||||||
|
config_get password "$section" "password"
|
||||||
|
|
||||||
|
if [ "$enabled" == 0 ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
authentication="$username:$password" yq -M -i '.authentication += [strenv(authentication)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_tun_dns_hijacks() {
|
||||||
|
dns_hijack="$1" yq -M -i '.tun.dns-hijack += [strenv(dns_hijack)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_fake_ip_filters() {
|
||||||
|
domain_name="$1" yq -M -i '.dns.fake-ip-filter += [strenv(domain_name)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_hosts() {
|
||||||
|
local section="$1"
|
||||||
|
|
||||||
|
local enabled domain_name
|
||||||
|
config_get_bool enabled "$section" "enabled" 0
|
||||||
|
config_get domain_name "$section" "domain_name"
|
||||||
|
|
||||||
|
if [ "$enabled" == 0 ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
config_list_foreach "$section" "ip" mixin_host "$domain_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_host() {
|
||||||
|
ip="$1" domain_name="$2" yq -M -i '.hosts.[strenv(domain_name)] += [strenv(ip)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_nameservers() {
|
||||||
|
local section="$1"
|
||||||
|
|
||||||
|
local enabled type
|
||||||
|
config_get_bool enabled "$section" "enabled" 0
|
||||||
|
config_get type "$section" "type"
|
||||||
|
|
||||||
|
if [ "$enabled" == 0 ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
config_list_foreach "$section" "nameserver" mixin_nameserver "$type"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_nameserver() {
|
||||||
|
nameserver="$1" type="$2" yq -M -i '.dns.[strenv(type)] += [strenv(nameserver)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_nameserver_policies() {
|
||||||
|
local section="$1"
|
||||||
|
|
||||||
|
local enabled matcher
|
||||||
|
config_get_bool enabled "$section" "enabled" 0
|
||||||
|
config_get matcher "$section" "matcher"
|
||||||
|
|
||||||
|
if [ "$enabled" == 0 ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
config_list_foreach "$section" "nameserver" mixin_nameserver_policy "$matcher"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_nameserver_policy() {
|
||||||
|
nameserver="$1" matcher="$2" yq -M -i '.dns.nameserver-policy.[strenv(matcher)] += [strenv(nameserver)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_sniffer_domain_names() {
|
||||||
|
domain_name="$1" type="$2" yq -M -i '.sniffer.[strenv(type)] += [strenv(domain_name)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_sniffs() {
|
||||||
|
local section="$1"
|
||||||
|
local enabled protocol overwrite_destination
|
||||||
|
config_get_bool enabled "$section" "enabled" 0
|
||||||
|
config_get protocol "$section" "protocol"
|
||||||
|
config_get_bool overwrite_destination "$section" "overwrite_destination" 0
|
||||||
|
if [ "$enabled" == 0 ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
protocol="$protocol" overwrite_destination="$overwrite_destination" yq -M -i '.sniffer.sniff.[strenv(protocol)].override-destination = env(overwrite_destination) == 1' "$RUN_PROFILE_PATH"
|
||||||
|
config_list_foreach "$section" "port" mixin_sniff "$protocol"
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin_sniff() {
|
||||||
|
port="$1" protocol="$2" yq -M -i '.sniffer.sniff.[strenv(protocol)].ports += [env(port)]' "$RUN_PROFILE_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
add_bypass_user() {
|
||||||
|
local user; user="$1"
|
||||||
|
if [ "$user" != "root" ] && (cut -d ':' -f 1 < /etc/passwd | grep -q "$user"); then
|
||||||
|
nft add element inet "$FW_TABLE" bypass_user \{ "$user" \}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
add_bypass_group() {
|
||||||
|
local group; group="$1"
|
||||||
|
if [ "$group" != "root" ] && (cut -d ':' -f 1 < /etc/group | grep -q "$group"); then
|
||||||
|
nft add element inet "$FW_TABLE" bypass_group \{ "$group" \}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
add_acl_ip() {
|
||||||
|
nft add element inet "$FW_TABLE" acl_ip \{ "$1" \}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_acl_ip6() {
|
||||||
|
nft add element inet "$FW_TABLE" acl_ip6 \{ "$1" \}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_acl_mac() {
|
||||||
|
nft add element inet "$FW_TABLE" acl_mac \{ "$1" \}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_acl_interface() {
|
||||||
|
local interface; interface="$1"
|
||||||
|
local device; network_get_device device "$interface"
|
||||||
|
if [ -n "$device" ]; then
|
||||||
|
nft add element inet "$FW_TABLE" acl_interface \{ "$device" \}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_subscription() {
|
||||||
|
local subscription_section; subscription_section="$1"
|
||||||
|
if [ -z "$subscription_section" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# load config
|
||||||
|
config_load nikki
|
||||||
|
# get subscription config
|
||||||
|
local subscription_name subscription_url subscription_user_agent
|
||||||
|
config_get subscription_name "$subscription_section" "name"
|
||||||
|
config_get subscription_url "$subscription_section" "url"
|
||||||
|
config_get subscription_user_agent "$subscription_section" "user_agent"
|
||||||
|
# reset subscription info
|
||||||
|
uci_remove "nikki" "$subscription_section" "expire"
|
||||||
|
uci_remove "nikki" "$subscription_section" "upload"
|
||||||
|
uci_remove "nikki" "$subscription_section" "download"
|
||||||
|
uci_remove "nikki" "$subscription_section" "total"
|
||||||
|
uci_remove "nikki" "$subscription_section" "used"
|
||||||
|
uci_remove "nikki" "$subscription_section" "avaliable"
|
||||||
|
uci_remove "nikki" "$subscription_section" "update"
|
||||||
|
uci_remove "nikki" "$subscription_section" "success"
|
||||||
|
# update subscription
|
||||||
|
log "Profile" "Update subscription: $subscription_name."
|
||||||
|
local subscription_header_tmpfile; subscription_header_tmpfile="/tmp/$subscription_section.header"
|
||||||
|
local subscription_tmpfile; subscription_tmpfile="/tmp/$subscription_section.yaml"
|
||||||
|
local subscription_file; subscription_file="$SUBSCRIPTIONS_DIR/$subscription_section.yaml"
|
||||||
|
if (curl -s -f --connect-timeout 15 --retry 3 -L -X GET -A "$subscription_user_agent" -D "$subscription_header_tmpfile" -o "$subscription_tmpfile" "$subscription_url"); then
|
||||||
|
log "Profile" "Subscription update successful."
|
||||||
|
local subscription_expire subscription_upload subscription_download subscription_total subscription_used subscription_avaliable
|
||||||
|
subscription_expire=$(grep "subscription-userinfo: " "$subscription_header_tmpfile" | grep -o -E "expire=[[:digit:]]+" | cut -d '=' -f 2)
|
||||||
|
subscription_upload=$(grep "subscription-userinfo: " "$subscription_header_tmpfile" | grep -o -E "upload=[[:digit:]]+" | cut -d '=' -f 2)
|
||||||
|
subscription_download=$(grep "subscription-userinfo: " "$subscription_header_tmpfile" | grep -o -E "download=[[:digit:]]+" | cut -d '=' -f 2)
|
||||||
|
subscription_total=$(grep "subscription-userinfo: " "$subscription_header_tmpfile" | grep -o -E "total=[[:digit:]]+" | cut -d '=' -f 2)
|
||||||
|
if [[ -n "$subscription_upload" && -n "$subscription_download" ]]; then
|
||||||
|
subscription_used=$((subscription_upload + subscription_download))
|
||||||
|
if [ -n "$subscription_total" ]; then
|
||||||
|
subscription_avaliable=$((subscription_total - subscription_upload - subscription_download))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# update subscription info
|
||||||
|
if [ -n "$subscription_expire" ]; then
|
||||||
|
uci_set "nikki" "$subscription_section" "expire" "$(date "+%Y-%m-%d %H:%M:%S" -d @$subscription_expire)"
|
||||||
|
fi
|
||||||
|
if [ -n "$subscription_upload" ]; then
|
||||||
|
uci_set "nikki" "$subscription_section" "upload" "$(format_filesize $subscription_upload)"
|
||||||
|
fi
|
||||||
|
if [ -n "$subscription_download" ]; then
|
||||||
|
uci_set "nikki" "$subscription_section" "download" "$(format_filesize $subscription_download)"
|
||||||
|
fi
|
||||||
|
if [ -n "$subscription_total" ]; then
|
||||||
|
uci_set "nikki" "$subscription_section" "total" "$(format_filesize $subscription_total)"
|
||||||
|
fi
|
||||||
|
if [ -n "$subscription_used" ]; then
|
||||||
|
uci_set "nikki" "$subscription_section" "used" "$(format_filesize $subscription_used)"
|
||||||
|
fi
|
||||||
|
if [ -n "$subscription_avaliable" ]; then
|
||||||
|
uci_set "nikki" "$subscription_section" "avaliable" "$(format_filesize $subscription_avaliable)"
|
||||||
|
fi
|
||||||
|
uci_set "nikki" "$subscription_section" "update" "$(date "+%Y-%m-%d %H:%M:%S")"
|
||||||
|
uci_set "nikki" "$subscription_section" "success" "1"
|
||||||
|
# update subscription file
|
||||||
|
rm -f "$subscription_header_tmpfile"
|
||||||
|
mv -f "$subscription_tmpfile" "$subscription_file"
|
||||||
|
else
|
||||||
|
log "Profile" "Subscription update failed."
|
||||||
|
# update subscription info
|
||||||
|
uci_set "nikki" "$subscription_section" "success" "0"
|
||||||
|
# remove tmpfile
|
||||||
|
rm -f "$subscription_header_tmpfile"
|
||||||
|
rm -f "$subscription_tmpfile"
|
||||||
|
fi
|
||||||
|
uci_commit "nikki"
|
||||||
|
}
|
5
nikki/files/nikki.upgrade
Normal file
5
nikki/files/nikki.upgrade
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/etc/nikki/profiles/
|
||||||
|
/etc/nikki/subscriptions/
|
||||||
|
/etc/nikki/mixin.yaml
|
||||||
|
/etc/nikki/nftables/reserved_ip.nft
|
||||||
|
/etc/nikki/nftables/reserved_ip6.nft
|
18
nikki/files/scripts/firewall_include.sh
Normal file
18
nikki/files/scripts/firewall_include.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "$IPKG_INSTROOT/lib/functions.sh"
|
||||||
|
. "$IPKG_INSTROOT/etc/nikki/scripts/include.sh"
|
||||||
|
|
||||||
|
config_load nikki
|
||||||
|
config_get enabled "config" "enabled" 0
|
||||||
|
config_get tcp_transparent_proxy_mode "proxy" "tcp_transparent_proxy_mode"
|
||||||
|
config_get udp_transparent_proxy_mode "proxy" "udp_transparent_proxy_mode"
|
||||||
|
config_get tun_device "mixin" "tun_device"
|
||||||
|
|
||||||
|
if [ "$enabled" == 1 ] && [[ "$tcp_transparent_proxy_mode" == "tun" || "$udp_transparent_proxy_mode" == "tun" ]]; then
|
||||||
|
nft insert rule inet fw4 input iifname "$tun_device" counter accept comment "nikki"
|
||||||
|
nft insert rule inet fw4 forward oifname "$tun_device" counter accept comment "nikki"
|
||||||
|
nft insert rule inet fw4 forward iifname "$tun_device" counter accept comment "nikki"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
97
nikki/files/scripts/include.sh
Normal file
97
nikki/files/scripts/include.sh
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# permission
|
||||||
|
NIKKI_USER="root"
|
||||||
|
NIKKI_GROUP="nikki"
|
||||||
|
|
||||||
|
# routing
|
||||||
|
FW_TABLE="nikki"
|
||||||
|
FW_MARK="0x80"
|
||||||
|
FW_MARK_MASK="0xFF"
|
||||||
|
TCP_RULE_PREF="1024"
|
||||||
|
UDP_RULE_PREF="1025"
|
||||||
|
TPROXY_ROUTE_TABLE="80"
|
||||||
|
TUN_ROUTE_TABLE="81"
|
||||||
|
|
||||||
|
# paths
|
||||||
|
PROG="/usr/bin/mihomo"
|
||||||
|
HOME_DIR="/etc/nikki"
|
||||||
|
PROFILES_DIR="$HOME_DIR/profiles"
|
||||||
|
SUBSCRIPTIONS_DIR="$HOME_DIR/subscriptions"
|
||||||
|
MIXIN_FILE_PATH="$HOME_DIR/mixin.yaml"
|
||||||
|
RUN_DIR="$HOME_DIR/run"
|
||||||
|
RUN_PROFILE_PATH="$RUN_DIR/config.yaml"
|
||||||
|
RUN_UI_DIR="$RUN_DIR/ui"
|
||||||
|
|
||||||
|
# log
|
||||||
|
LOG_DIR="/var/log/nikki"
|
||||||
|
APP_LOG_PATH="$LOG_DIR/app.log"
|
||||||
|
CORE_LOG_PATH="$LOG_DIR/core.log"
|
||||||
|
|
||||||
|
# flag
|
||||||
|
FLAG_DIR="/var/run/nikki"
|
||||||
|
STARTED_FLAG="$FLAG_DIR/started.flag"
|
||||||
|
BRIDGE_NF_CALL_IPTABLES_FLAG="$FLAG_DIR/bridge_nf_call_iptables.flag"
|
||||||
|
BRIDGE_NF_CALL_IP6TABLES_FLAG="$FLAG_DIR/bridge_nf_call_ip6tables.flag"
|
||||||
|
|
||||||
|
# scripts
|
||||||
|
SH_DIR="$HOME_DIR/scripts"
|
||||||
|
INCLUDE_SH="$SH_DIR/include.sh"
|
||||||
|
FIREWALL_INCLUDE_SH="$SH_DIR/firewall_include.sh"
|
||||||
|
|
||||||
|
# nftables
|
||||||
|
NFT_DIR="$HOME_DIR/nftables"
|
||||||
|
HIJACK_NFT="$NFT_DIR/hijack.nft"
|
||||||
|
RESERVED_IP_NFT="$NFT_DIR/reserved_ip.nft"
|
||||||
|
RESERVED_IP6_NFT="$NFT_DIR/reserved_ip6.nft"
|
||||||
|
GEOIP_CN_NFT="$NFT_DIR/geoip_cn.nft"
|
||||||
|
GEOIP6_CN_NFT="$NFT_DIR/geoip6_cn.nft"
|
||||||
|
|
||||||
|
# functions
|
||||||
|
format_filesize() {
|
||||||
|
local kb; kb=1024
|
||||||
|
local mb; mb=$((kb * 1024))
|
||||||
|
local gb; gb=$((mb * 1024))
|
||||||
|
local tb; tb=$((gb * 1024))
|
||||||
|
local pb; pb=$((tb * 1024))
|
||||||
|
local size; size="$1"
|
||||||
|
if [ -z "$size" ]; then
|
||||||
|
echo ""
|
||||||
|
elif [ "$size" -lt "$kb" ]; then
|
||||||
|
echo "$size B"
|
||||||
|
elif [ "$size" -lt "$mb" ]; then
|
||||||
|
echo "$(awk "BEGIN {print $size / $kb}") KB"
|
||||||
|
elif [ "$size" -lt "$gb" ]; then
|
||||||
|
echo "$(awk "BEGIN {print $size / $mb}") MB"
|
||||||
|
elif [ "$size" -lt "$tb" ]; then
|
||||||
|
echo "$(awk "BEGIN {print $size / $gb}") GB"
|
||||||
|
elif [ "$size" -lt "$pb" ]; then
|
||||||
|
echo "$(awk "BEGIN {print $size / $tb}") TB"
|
||||||
|
else
|
||||||
|
echo "$(awk "BEGIN {print $size / $pb}") PB"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_files() {
|
||||||
|
if [ ! -d "$LOG_DIR" ]; then
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
fi
|
||||||
|
if [ ! -f "$APP_LOG_PATH" ]; then
|
||||||
|
touch "$APP_LOG_PATH"
|
||||||
|
fi
|
||||||
|
if [ ! -f "$CORE_LOG_PATH" ]; then
|
||||||
|
touch "$CORE_LOG_PATH"
|
||||||
|
fi
|
||||||
|
if [ ! -d "$FLAG_DIR" ]; then
|
||||||
|
mkdir -p "$FLAG_DIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_log() {
|
||||||
|
echo -n > "$APP_LOG_PATH"
|
||||||
|
echo -n > "$CORE_LOG_PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "[$(date "+%Y-%m-%d %H:%M:%S")] [$1] $2" >> "$APP_LOG_PATH"
|
||||||
|
}
|
12
nikki/files/uci-defaults/firewall.sh
Normal file
12
nikki/files/uci-defaults/firewall.sh
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "$IPKG_INSTROOT/etc/nikki/scripts/include.sh"
|
||||||
|
|
||||||
|
uci -q batch <<-EOF > /dev/null
|
||||||
|
del firewall.nikki
|
||||||
|
set firewall.nikki=include
|
||||||
|
set firewall.nikki.type=script
|
||||||
|
set firewall.nikki.path=$FIREWALL_INCLUDE_SH
|
||||||
|
set firewall.nikki.fw4_compatible=1
|
||||||
|
commit firewall
|
||||||
|
EOF
|
24
nikki/files/uci-defaults/init.sh
Normal file
24
nikki/files/uci-defaults/init.sh
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "$IPKG_INSTROOT/etc/nikki/scripts/include.sh"
|
||||||
|
|
||||||
|
# check nikki.config.init
|
||||||
|
init=$(uci -q get nikki.config.init); [ -z "$init" ] && return
|
||||||
|
|
||||||
|
# generate random string for api secret and authentication password
|
||||||
|
random=$(awk 'BEGIN{srand(); print int(rand() * 1000000)}')
|
||||||
|
|
||||||
|
# set nikki.mixin.api_secret
|
||||||
|
uci set nikki.mixin.api_secret="$random"
|
||||||
|
|
||||||
|
# set nikki.@authentication[0].password
|
||||||
|
uci set nikki.@authentication[0].password="$random"
|
||||||
|
|
||||||
|
# remove nikki.config.init
|
||||||
|
uci del nikki.config.init
|
||||||
|
|
||||||
|
# commit
|
||||||
|
uci commit nikki
|
||||||
|
|
||||||
|
# exit with 0
|
||||||
|
exit 0
|
9
nikki/files/uci-defaults/migrate.sh
Normal file
9
nikki/files/uci-defaults/migrate.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "$IPKG_INSTROOT/etc/nikki/scripts/include.sh"
|
||||||
|
|
||||||
|
# commit
|
||||||
|
uci commit nikki
|
||||||
|
|
||||||
|
# exit with 0
|
||||||
|
exit 0
|
Loading…
Reference in New Issue
Block a user