mirror of
https://github.com/3proxy/3proxy.git
synced 2026-09-29 16:55:51 +08:00
Compare commits
No commits in common. "a11427afe93de57573e1546c6d91f56221c196fc" and "754ba7115a48bf0681afa8e46da16ef9cbe56917" have entirely different histories.
a11427afe9
...
754ba7115a
139
.github/workflows/build-ipk.yml
vendored
139
.github/workflows/build-ipk.yml
vendored
@ -1,139 +0,0 @@
|
|||||||
name: OpenWrt ipk build
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
|
||||||
OPENWRT_RELEASE: 24.10.0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ipk:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
id-token: write
|
|
||||||
attestations: write
|
|
||||||
name: "${{ matrix.arch }}"
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- target: ramips/mt7621
|
|
||||||
arch: mipsel_24kc
|
|
||||||
- target: ath79/generic
|
|
||||||
arch: mips_24kc
|
|
||||||
- target: ipq40xx/generic
|
|
||||||
arch: arm_cortex-a7_neon-vfpv4
|
|
||||||
- target: mediatek/filogic
|
|
||||||
arch: aarch64_cortex-a53
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v7
|
|
||||||
|
|
||||||
- name: env
|
|
||||||
run: echo "RELEASE=$(tr -d ' \t\r\n' < RELEASE)" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Install build dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y build-essential libncurses-dev zlib1g-dev gawk git \
|
|
||||||
gettext libssl-dev xsltproc wget unzip python3 rsync file zstd
|
|
||||||
|
|
||||||
- name: Fetch SDK
|
|
||||||
run: |
|
|
||||||
BASE="https://downloads.openwrt.org/releases/$OPENWRT_RELEASE/targets/${{ matrix.target }}"
|
|
||||||
# The SDK file name carries the toolchain flavour, which differs between
|
|
||||||
# targets (musl vs musl_eabi), so take it from the directory listing.
|
|
||||||
NAME=$(curl -fsSL "$BASE/" | grep -oE 'openwrt-sdk-[^"]*\.tar\.zst' | head -1)
|
|
||||||
if [ -z "$NAME" ]; then echo "no SDK for ${{ matrix.target }}"; exit 1; fi
|
|
||||||
echo "fetching $NAME"
|
|
||||||
curl -fsSL "$BASE/$NAME" -o sdk.tar.zst
|
|
||||||
tar --zstd -xf sdk.tar.zst
|
|
||||||
mv "${NAME%.tar.zst}" sdk
|
|
||||||
rm sdk.tar.zst
|
|
||||||
|
|
||||||
- name: Stage the package
|
|
||||||
run: |
|
|
||||||
mkdir -p sdk/package/3proxy sdk/dl
|
|
||||||
cp -a scripts/openwrt/. sdk/package/3proxy/
|
|
||||||
# Build the checkout rather than a published tarball, so the workflow
|
|
||||||
# does not depend on the release archive existing yet.
|
|
||||||
git archive --format=tar.gz --prefix="3proxy-$RELEASE/" -o "sdk/dl/3proxy-$RELEASE.tar.gz" HEAD
|
|
||||||
HASH=$(sha256sum "sdk/dl/3proxy-$RELEASE.tar.gz" | cut -d' ' -f1)
|
|
||||||
sed -i "s|^PKG_VERSION:=.*|PKG_VERSION:=$RELEASE|" sdk/package/3proxy/Makefile
|
|
||||||
sed -i "s|^PKG_HASH:=.*|PKG_HASH:=$HASH|" sdk/package/3proxy/Makefile
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
cd sdk
|
|
||||||
./scripts/feeds update base packages
|
|
||||||
./scripts/feeds install libopenssl libpcre2
|
|
||||||
echo CONFIG_PACKAGE_3proxy=m >> .config
|
|
||||||
make defconfig
|
|
||||||
make package/3proxy/compile -j$(nproc)
|
|
||||||
|
|
||||||
- name: Collect
|
|
||||||
run: |
|
|
||||||
find sdk/bin -name '3proxy_*.ipk' -exec cp {} . \;
|
|
||||||
ls -l *.ipk
|
|
||||||
for f in *.ipk; do echo "$f"; done
|
|
||||||
|
|
||||||
- name: Get artifact ipk
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: "3proxy-${{ env.RELEASE }}-${{ matrix.arch }}.ipk"
|
|
||||||
path: "*.ipk"
|
|
||||||
|
|
||||||
- name: Import signing key
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
|
||||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
|
||||||
run: |
|
|
||||||
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
|
|
||||||
mkdir -p ~/.gnupg && chmod 700 ~/.gnupg
|
|
||||||
printf 'allow-loopback-pinentry\ndefault-cache-ttl 7200\nmax-cache-ttl 7200\n' > ~/.gnupg/gpg-agent.conf
|
|
||||||
gpgconf --kill gpg-agent || true
|
|
||||||
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
|
|
||||||
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
|
|
||||||
echo "GPG_KEYID=$KEYID" >> $GITHUB_ENV
|
|
||||||
echo prime > /tmp/prime.txt
|
|
||||||
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
|
||||||
-u "$KEYID" --detach-sign -o /dev/null /tmp/prime.txt
|
|
||||||
rm -f /tmp/prime.txt
|
|
||||||
|
|
||||||
- name: Checksums and detached signatures
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
|
||||||
run: |
|
|
||||||
# opkg verifies the signature of a feed index, never of a package file,
|
|
||||||
# so the checksums and their signature are what a manual install can be
|
|
||||||
# checked against.
|
|
||||||
sha256sum *.ipk > SHA256SUMS-openwrt-${{ matrix.arch }}
|
|
||||||
for f in *.ipk SHA256SUMS-openwrt-${{ matrix.arch }}; do
|
|
||||||
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
|
||||||
-u "$GPG_KEYID" --armor --detach-sign "$f"
|
|
||||||
done
|
|
||||||
sha256sum -c SHA256SUMS-openwrt-${{ matrix.arch }}
|
|
||||||
gpg --verify SHA256SUMS-openwrt-${{ matrix.arch }}.asc SHA256SUMS-openwrt-${{ matrix.arch }}
|
|
||||||
|
|
||||||
- name: Attest build provenance
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
uses: actions/attest-build-provenance@v2
|
|
||||||
with:
|
|
||||||
subject-path: |
|
|
||||||
*.ipk
|
|
||||||
|
|
||||||
- name: Upload to release
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
|
||||||
run: |
|
|
||||||
gh release upload "$TAG" *.ipk *.ipk.asc \
|
|
||||||
SHA256SUMS-openwrt-${{ matrix.arch }} SHA256SUMS-openwrt-${{ matrix.arch }}.asc
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (C) 2026 3proxy.org
|
|
||||||
#
|
|
||||||
# This is free software, licensed under the BSD 3-Clause License.
|
|
||||||
#
|
|
||||||
|
|
||||||
include $(TOPDIR)/rules.mk
|
|
||||||
|
|
||||||
PKG_NAME:=3proxy
|
|
||||||
PKG_VERSION:=0.9.9.0
|
|
||||||
PKG_RELEASE:=1
|
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
|
||||||
# A trailing ? tells the download helper the URL is complete and PKG_SOURCE
|
|
||||||
# must not be appended to it.
|
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/3proxy/3proxy/tar.gz/refs/tags/$(PKG_VERSION)?
|
|
||||||
PKG_HASH:=5af253fa734f61af6d5fe3790022130a14caf25bfce24a6aefd415797d351dd3
|
|
||||||
|
|
||||||
PKG_MAINTAINER:=Vladimir Dubrovin <vlad@3proxy.org>
|
|
||||||
PKG_LICENSE:=BSD-3-Clause
|
|
||||||
PKG_LICENSE_FILES:=copying
|
|
||||||
PKG_CPE_ID:=cpe:/a:3proxy:3proxy
|
|
||||||
|
|
||||||
PKG_BUILD_PARALLEL:=1
|
|
||||||
|
|
||||||
include $(INCLUDE_DIR)/package.mk
|
|
||||||
|
|
||||||
define Package/3proxy
|
|
||||||
SECTION:=net
|
|
||||||
CATEGORY:=Network
|
|
||||||
SUBMENU:=Web Servers/Proxies
|
|
||||||
TITLE:=tiny free proxy server
|
|
||||||
URL:=https://3proxy.org/
|
|
||||||
DEPENDS:=+libopenssl +libpcre2
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/3proxy/description
|
|
||||||
3proxy is a tiny free proxy server supporting HTTP, HTTPS, FTP, SOCKS v4/v4a/v5,
|
|
||||||
POP3, SMTP, IMAP, TCP and UDP port mapping, with access control, bandwidth
|
|
||||||
limiting and traffic accounting.
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/3proxy/conffiles
|
|
||||||
/etc/config/3proxy
|
|
||||||
endef
|
|
||||||
|
|
||||||
# Makefile.Linux appends to CFLAGS and LDFLAGS internally; the target flags have
|
|
||||||
# to be added rather than substituted, or the defines it relies on are lost.
|
|
||||||
define Build/Compile
|
|
||||||
$(MAKE) -C $(PKG_BUILD_DIR) -f Makefile.Linux \
|
|
||||||
CC="$(TARGET_CC)" \
|
|
||||||
EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
|
|
||||||
EXTRA_LDFLAGS="$(TARGET_LDFLAGS)" \
|
|
||||||
PLUGINS=
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/3proxy/install
|
|
||||||
$(INSTALL_DIR) $(1)/usr/bin
|
|
||||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/3proxy $(1)/usr/bin/3proxy
|
|
||||||
$(INSTALL_DIR) $(1)/etc/config
|
|
||||||
$(INSTALL_CONF) ./files/3proxy.config $(1)/etc/config/3proxy
|
|
||||||
$(INSTALL_DIR) $(1)/etc/init.d
|
|
||||||
$(INSTALL_BIN) ./files/3proxy.init $(1)/etc/init.d/3proxy
|
|
||||||
endef
|
|
||||||
|
|
||||||
$(eval $(call BuildPackage,3proxy))
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
config 3proxy 'global'
|
|
||||||
option enabled '0'
|
|
||||||
option nscache '65536'
|
|
||||||
# option nscache6 '65536'
|
|
||||||
# static records, added to the cache; 0.0.0.0 blackholes a name
|
|
||||||
# list nsrecord 'ads.example.com 0.0.0.0'
|
|
||||||
option maxconn '128'
|
|
||||||
option auth 'iponly'
|
|
||||||
option log 'syslog'
|
|
||||||
# option timeouts '1 5 30 60 180 1800 15 60 15 5 5'
|
|
||||||
# list include '/etc/3proxy/extra.cfg'
|
|
||||||
list nserver '8.8.8.8'
|
|
||||||
list nserver '8.8.4.4'
|
|
||||||
# list user 'admin:CL:password'
|
|
||||||
# list extra_config 'timeouts 1 5 30 60 180 1800 15 60'
|
|
||||||
# access list used by services which do not define their own
|
|
||||||
list acl 'lan'
|
|
||||||
|
|
||||||
# Access rules are named sections referenced by services. The order of the
|
|
||||||
# references decides precedence: 3proxy stops at the first rule that matches.
|
|
||||||
config acl 'lan'
|
|
||||||
option action 'allow'
|
|
||||||
option src '192.168.1.0/24'
|
|
||||||
|
|
||||||
config acl 'deny_private'
|
|
||||||
option action 'deny'
|
|
||||||
option dst '10.0.0.0/8,172.16.0.0/12,192.168.0.0/16'
|
|
||||||
|
|
||||||
#config acl 'via_upstream'
|
|
||||||
# option action 'allow'
|
|
||||||
# list parent 'upstream'
|
|
||||||
|
|
||||||
# Parent proxies extend an allow rule to build a chain. Weights group them:
|
|
||||||
# parents whose weights sum to 1000 form one group and one is picked at random,
|
|
||||||
# several groups are chained in order.
|
|
||||||
#config parent 'upstream'
|
|
||||||
# option weight '1000'
|
|
||||||
# option type 'socks5'
|
|
||||||
# option ip '10.0.0.1'
|
|
||||||
# option port '1080'
|
|
||||||
# option username ''
|
|
||||||
# option password ''
|
|
||||||
|
|
||||||
config service 'proxy'
|
|
||||||
option enabled '0'
|
|
||||||
option type 'proxy'
|
|
||||||
option port '3128'
|
|
||||||
# option bind ''
|
|
||||||
# option external ''
|
|
||||||
# option extra ''
|
|
||||||
# option auth 'strong'
|
|
||||||
list acl 'deny_private'
|
|
||||||
list acl 'lan'
|
|
||||||
|
|
||||||
config service 'socks'
|
|
||||||
option enabled '0'
|
|
||||||
option type 'socks'
|
|
||||||
option port '1080'
|
|
||||||
list acl 'lan'
|
|
||||||
@ -1,460 +0,0 @@
|
|||||||
#!/bin/sh /etc/rc.common
|
|
||||||
|
|
||||||
START=50
|
|
||||||
USE_PROCD=1
|
|
||||||
|
|
||||||
CFGFILE=/var/etc/3proxy.cfg
|
|
||||||
PROG=/usr/bin/3proxy
|
|
||||||
|
|
||||||
# 3proxy.cfg is order dependent: authentication and access rules apply to the
|
|
||||||
# service lines that follow them, and the access list has to be flushed before
|
|
||||||
# each service. The file is written as one global block followed by one block
|
|
||||||
# per service.
|
|
||||||
|
|
||||||
acl_written=0
|
|
||||||
|
|
||||||
append_line() {
|
|
||||||
echo "$1" >> "$CFGFILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
append_include() {
|
|
||||||
echo "include $1" >> "$CFGFILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# The limiter directives carry their own ACL pattern rather than attaching to a
|
|
||||||
# preceding allow rule, and 3proxy defaults every omitted field to *, so the
|
|
||||||
# trailing wildcards are dropped again to keep the file readable.
|
|
||||||
# logformat takes a single argument, so a format containing spaces has to be
|
|
||||||
# quoted. Quotes already present in the UCI value are not doubled.
|
|
||||||
append_logformat() {
|
|
||||||
local fmt="$1"
|
|
||||||
|
|
||||||
case "$fmt" in
|
|
||||||
'"'*'"') ;;
|
|
||||||
*) fmt="\"$fmt\"" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "logformat $fmt" >> "$CFGFILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
limit_match() {
|
|
||||||
local users src dst ports ops weekdays periods out
|
|
||||||
|
|
||||||
config_get users "$1" users '*'
|
|
||||||
config_get src "$1" src '*'
|
|
||||||
config_get dst "$1" dst '*'
|
|
||||||
config_get ports "$1" ports '*'
|
|
||||||
config_get ops "$1" operations '*'
|
|
||||||
config_get weekdays "$1" weekdays '*'
|
|
||||||
config_get periods "$1" timeperiods '*'
|
|
||||||
|
|
||||||
out="$users $src $dst $ports $ops $weekdays $periods"
|
|
||||||
while [ "${out% \*}" != "$out" ]; do out="${out% \*}"; done
|
|
||||||
|
|
||||||
echo "$out"
|
|
||||||
}
|
|
||||||
|
|
||||||
append_limit() {
|
|
||||||
local type rate period number count_type limit match
|
|
||||||
|
|
||||||
config_get type "$1" type
|
|
||||||
|
|
||||||
case "$type" in
|
|
||||||
bandlimin|bandlimout|nobandlimin|nobandlimout|\
|
|
||||||
connlim|noconnlim|\
|
|
||||||
countin|countout|countall|nocountin|nocountout|nocountall) ;;
|
|
||||||
*)
|
|
||||||
echo "3proxy: limit '$1' has unknown type '$type', ignored" >&2
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
match=$(limit_match "$1")
|
|
||||||
|
|
||||||
case "$type" in
|
|
||||||
bandlimin|bandlimout)
|
|
||||||
config_get rate "$1" rate
|
|
||||||
[ -n "$rate" ] || {
|
|
||||||
echo "3proxy: limit '$1' needs a rate, ignored" >&2
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
echo "$type $rate $match" >> "$CFGFILE"
|
|
||||||
;;
|
|
||||||
connlim)
|
|
||||||
config_get rate "$1" rate
|
|
||||||
config_get period "$1" period 0
|
|
||||||
[ -n "$rate" ] || {
|
|
||||||
echo "3proxy: limit '$1' needs a rate, ignored" >&2
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
echo "$type $rate $period $match" >> "$CFGFILE"
|
|
||||||
;;
|
|
||||||
countin|countout|countall)
|
|
||||||
config_get number "$1" number
|
|
||||||
config_get count_type "$1" count_type
|
|
||||||
config_get limit "$1" limit
|
|
||||||
[ -n "$number" ] && [ -n "$count_type" ] && [ -n "$limit" ] || {
|
|
||||||
echo "3proxy: limit '$1' needs number, count_type and limit, ignored" >&2
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
echo "$type $number $count_type $limit $match" >> "$CFGFILE"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "$type $match" >> "$CFGFILE"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
append_pcre_extend() {
|
|
||||||
echo "pcre_extend $1" >> "$CFGFILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
append_pcre() {
|
|
||||||
local match_type action regexp rewrite ace
|
|
||||||
|
|
||||||
config_get match_type "$1" match_type
|
|
||||||
config_get action "$1" action
|
|
||||||
config_get regexp "$1" regexp
|
|
||||||
config_get rewrite "$1" rewrite
|
|
||||||
config_get ace "$1" ace
|
|
||||||
|
|
||||||
[ -n "$match_type" ] && [ -n "$action" ] && [ -n "$regexp" ] || {
|
|
||||||
echo "3proxy: pcre '$1' needs match_type, action and regexp, ignored" >&2
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Catch bad values here: 3proxy rejects the whole configuration on an
|
|
||||||
# unknown type or action, which would leave the router without a proxy.
|
|
||||||
case "$action" in
|
|
||||||
allow|deny|dunno) ;;
|
|
||||||
*)
|
|
||||||
echo "3proxy: pcre '$1' action '$action' is not allow, deny or dunno, ignored" >&2
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
local part
|
|
||||||
for part in $(echo "$match_type" | tr ',' ' '); do
|
|
||||||
case "$part" in
|
|
||||||
request|cliheader|srvheader|clidata|srvdata) ;;
|
|
||||||
*)
|
|
||||||
echo "3proxy: pcre '$1' match_type '$part' is unknown, ignored" >&2
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$rewrite" ]; then
|
|
||||||
echo "pcre_rewrite $match_type $action $regexp $rewrite${ace:+ $ace}" >> "$CFGFILE"
|
|
||||||
else
|
|
||||||
echo "pcre $match_type $action $regexp${ace:+ $ace}" >> "$CFGFILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
config_list_foreach "$1" extend append_pcre_extend
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
append_nsrecord() {
|
|
||||||
set -- $1
|
|
||||||
if [ $# -ne 2 ]; then
|
|
||||||
echo "3proxy: nsrecord '$*' needs a hostname and an address, ignored" >&2
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "nsrecord $1 $2" >> "$CFGFILE"
|
|
||||||
nsrecord_written=1
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
append_nserver() {
|
|
||||||
echo "nserver $1" >> "$CFGFILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
append_user() {
|
|
||||||
users="$users $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 is the name of an acl section referenced by a service, or by the global
|
|
||||||
# section as the default access list.
|
|
||||||
append_acl() {
|
|
||||||
local action users src dst ports
|
|
||||||
|
|
||||||
config_get action "$1" action allow
|
|
||||||
config_get users "$1" users
|
|
||||||
config_get src "$1" src
|
|
||||||
config_get dst "$1" dst
|
|
||||||
config_get ports "$1" ports
|
|
||||||
|
|
||||||
case "$action" in
|
|
||||||
allow|deny) ;;
|
|
||||||
*)
|
|
||||||
echo "3proxy: acl '$1' has unknown action '$action', ignored" >&2
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "$action ${users:-*} ${src:-*} ${dst:-*} ${ports:-*}" >> "$CFGFILE"
|
|
||||||
acl_written=1
|
|
||||||
|
|
||||||
if [ "$action" = "allow" ]; then
|
|
||||||
config_list_foreach "$1" parent append_parent
|
|
||||||
else
|
|
||||||
config_get _parent "$1" parent
|
|
||||||
[ -z "$_parent" ] || echo "3proxy: acl '$1' is a deny rule, its parents are ignored" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# $1 is the name of a parent section referenced by an acl. "parent" extends the
|
|
||||||
# allow rule that precedes it, so these are emitted directly after their rule.
|
|
||||||
append_parent() {
|
|
||||||
local weight type ip port username password line
|
|
||||||
|
|
||||||
config_get weight "$1" weight 1000
|
|
||||||
config_get type "$1" type
|
|
||||||
config_get ip "$1" ip
|
|
||||||
config_get port "$1" port
|
|
||||||
config_get username "$1" username
|
|
||||||
config_get password "$1" password
|
|
||||||
|
|
||||||
[ -n "$type" ] && [ -n "$ip" ] && [ -n "$port" ] || {
|
|
||||||
echo "3proxy: parent '$1' needs type, ip and port, ignored" >&2
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
line="parent $weight $type $ip $port"
|
|
||||||
if [ -n "$username" ]; then
|
|
||||||
line="$line $username"
|
|
||||||
[ -n "$password" ] && line="$line $password"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$line" >> "$CFGFILE"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# TLS parameters that take a value. The UCI option name is the directive name.
|
|
||||||
SSL_VALUE_OPTIONS="ssl_server_cert ssl_server_key ssl_client_cert ssl_client_key
|
|
||||||
ssl_client_ciphersuites ssl_server_ciphersuites
|
|
||||||
ssl_client_cipher_list ssl_server_cipher_list
|
|
||||||
ssl_client_min_proto_version ssl_server_min_proto_version
|
|
||||||
ssl_client_max_proto_version ssl_server_max_proto_version
|
|
||||||
ssl_server_ca_file ssl_server_ca_key ssl_server_ca_dir ssl_server_ca_store
|
|
||||||
ssl_client_ca_file ssl_client_ca_dir ssl_client_ca_store
|
|
||||||
ssl_client_sni ssl_client_alpn ssl_client_mode ssl_certcache"
|
|
||||||
|
|
||||||
# The TLS switches apply to every service below them, so they leak from one
|
|
||||||
# service to the next unless turned back off. These track what is currently in
|
|
||||||
# effect - all off, matching the defaults - so a directive is written only when
|
|
||||||
# a service actually needs a different state.
|
|
||||||
ssl_state_mitm=0
|
|
||||||
ssl_state_server=0
|
|
||||||
ssl_state_client=0
|
|
||||||
ssl_state_client_verify=0
|
|
||||||
ssl_state_server_verify=0
|
|
||||||
|
|
||||||
# $1 section, $2 uci option, $3 state variable, $4 directive on, $5 directive off
|
|
||||||
append_ssl_toggle() {
|
|
||||||
local want have
|
|
||||||
|
|
||||||
config_get_bool want "$1" "$2" 0
|
|
||||||
have=$(eval echo \$$3)
|
|
||||||
|
|
||||||
[ "$want" = "$have" ] && return 0
|
|
||||||
|
|
||||||
if [ "$want" -gt 0 ]; then
|
|
||||||
echo "$4" >> "$CFGFILE"
|
|
||||||
else
|
|
||||||
echo "$5" >> "$CFGFILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
eval "$3=$want"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
append_ssl() {
|
|
||||||
local opt value mitm server cert key cverify
|
|
||||||
|
|
||||||
for opt in $SSL_VALUE_OPTIONS; do
|
|
||||||
config_get value "$1" "$opt"
|
|
||||||
[ -n "$value" ] && echo "$opt $value" >> "$CFGFILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
append_ssl_toggle "$1" ssl_mitm ssl_state_mitm ssl_mitm ssl_nomitm
|
|
||||||
append_ssl_toggle "$1" ssl_server ssl_state_server ssl_serv ssl_noserv
|
|
||||||
append_ssl_toggle "$1" ssl_client ssl_state_client ssl_cli ssl_nocli
|
|
||||||
append_ssl_toggle "$1" ssl_client_verify ssl_state_client_verify \
|
|
||||||
ssl_client_verify ssl_client_no_verify
|
|
||||||
append_ssl_toggle "$1" ssl_server_verify ssl_state_server_verify \
|
|
||||||
ssl_server_verify ssl_server_no_verify
|
|
||||||
|
|
||||||
config_get_bool mitm "$1" ssl_mitm 0
|
|
||||||
config_get_bool cverify "$1" ssl_client_verify 0
|
|
||||||
[ "$mitm" -gt 0 ] && [ "$cverify" -gt 0 ] || [ "$mitm" -eq 0 ] || \
|
|
||||||
echo "3proxy: service '$1' spoofs certificates without ssl_client_verify, upstream certificates are not checked" >&2
|
|
||||||
|
|
||||||
config_get_bool server "$1" ssl_server 0
|
|
||||||
if [ "$server" -gt 0 ]; then
|
|
||||||
config_get cert "$1" ssl_server_cert
|
|
||||||
config_get key "$1" ssl_server_key
|
|
||||||
[ -n "$cert" ] && [ -n "$key" ] || \
|
|
||||||
echo "3proxy: service '$1' requires TLS from clients but has no ssl_server_cert/ssl_server_key" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
append_service() {
|
|
||||||
local enabled type port bind external extra auth args
|
|
||||||
local bind_interface external_interface logformat
|
|
||||||
|
|
||||||
config_get_bool enabled "$1" enabled 0
|
|
||||||
[ "$enabled" -gt 0 ] || return 0
|
|
||||||
|
|
||||||
config_get type "$1" type
|
|
||||||
[ -n "$type" ] || {
|
|
||||||
echo "3proxy: service '$1' has no type, ignored" >&2
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
config_get port "$1" port
|
|
||||||
config_get bind "$1" bind
|
|
||||||
config_get external "$1" external
|
|
||||||
config_get extra "$1" extra
|
|
||||||
config_get bind_interface "$1" bind_interface
|
|
||||||
config_get external_interface "$1" external_interface
|
|
||||||
config_get logformat "$1" logformat
|
|
||||||
config_get auth "$1" auth "$global_auth"
|
|
||||||
|
|
||||||
echo "" >> "$CFGFILE"
|
|
||||||
echo "flush" >> "$CFGFILE"
|
|
||||||
[ -n "$auth" ] && echo "auth $auth" >> "$CFGFILE"
|
|
||||||
|
|
||||||
# Rules referenced by the service, in the order they are listed. A service
|
|
||||||
# without its own list falls back to the global one.
|
|
||||||
acl_written=0
|
|
||||||
config_list_foreach "$1" acl append_acl
|
|
||||||
[ "$acl_written" -gt 0 ] || config_list_foreach global acl append_acl
|
|
||||||
|
|
||||||
[ -n "$logformat" ] && append_logformat "$logformat"
|
|
||||||
|
|
||||||
append_ssl "$1"
|
|
||||||
|
|
||||||
args=""
|
|
||||||
[ -n "$port" ] && args="$args -p$port"
|
|
||||||
[ -n "$bind" ] && args="$args -i$bind"
|
|
||||||
[ -n "$external" ] && args="$args -e$external"
|
|
||||||
[ -n "$bind_interface" ] && args="$args -Di$bind_interface"
|
|
||||||
[ -n "$external_interface" ] && args="$args -De$external_interface"
|
|
||||||
[ -n "$extra" ] && args="$args $extra"
|
|
||||||
|
|
||||||
echo "$type$args" >> "$CFGFILE"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
write_config() {
|
|
||||||
local nscache nscache6 maxconn log timeouts fakeresolve logformat
|
|
||||||
local authcache_type authcache_time authcache_size
|
|
||||||
local counter_file counter_type counter_name pcre_options
|
|
||||||
|
|
||||||
mkdir -p "$(dirname "$CFGFILE")"
|
|
||||||
: > "$CFGFILE"
|
|
||||||
|
|
||||||
config_get nscache global nscache
|
|
||||||
config_get nscache6 global nscache6
|
|
||||||
config_get maxconn global maxconn
|
|
||||||
config_get global_auth global auth iponly
|
|
||||||
config_get log global log syslog
|
|
||||||
config_get timeouts global timeouts
|
|
||||||
config_get logformat global logformat
|
|
||||||
config_get_bool fakeresolve global fakeresolve 0
|
|
||||||
config_get authcache_type global authcache_type
|
|
||||||
config_get authcache_time global authcache_time
|
|
||||||
config_get authcache_size global authcache_size
|
|
||||||
config_get counter_file global counter_file
|
|
||||||
config_get counter_type global counter_type
|
|
||||||
config_get counter_name global counter_name
|
|
||||||
config_get pcre_options global pcre_options
|
|
||||||
|
|
||||||
config_list_foreach global nserver append_nserver
|
|
||||||
[ -n "$nscache" ] && echo "nscache $nscache" >> "$CFGFILE"
|
|
||||||
[ -n "$nscache6" ] && echo "nscache6 $nscache6" >> "$CFGFILE"
|
|
||||||
|
|
||||||
# Static records are added to the cache, so they have to come after it.
|
|
||||||
nsrecord_written=0
|
|
||||||
config_list_foreach global nsrecord append_nsrecord
|
|
||||||
[ "$nsrecord_written" -eq 0 ] || [ -n "$nscache$nscache6" ] || \
|
|
||||||
echo "3proxy: nsrecord needs nscache or nscache6 to be set" >&2
|
|
||||||
|
|
||||||
case "$log" in
|
|
||||||
syslog) echo "log" >> "$CFGFILE" ;;
|
|
||||||
none|"") ;;
|
|
||||||
*) echo "log $log" >> "$CFGFILE" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
users=""
|
|
||||||
config_list_foreach global user append_user
|
|
||||||
[ -n "$users" ] && echo "users$users" >> "$CFGFILE"
|
|
||||||
|
|
||||||
[ -n "$timeouts" ] && echo "timeouts $timeouts" >> "$CFGFILE"
|
|
||||||
[ "$fakeresolve" -gt 0 ] && echo "fakeresolve" >> "$CFGFILE"
|
|
||||||
[ -n "$logformat" ] && append_logformat "$logformat"
|
|
||||||
|
|
||||||
if [ -n "$authcache_type" ]; then
|
|
||||||
[ -n "$authcache_time" ] || authcache_time=600
|
|
||||||
echo "authcache $authcache_type $authcache_time${authcache_size:+ $authcache_size}" >> "$CFGFILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$counter_file" ]; then
|
|
||||||
echo "counter $counter_file${counter_type:+ $counter_type}${counter_name:+ $counter_name}" >> "$CFGFILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
[ -n "$pcre_options" ] && echo "pcre_options $pcre_options" >> "$CFGFILE"
|
|
||||||
|
|
||||||
# Both lists are order sensitive: 3proxy stops at the first match, so the
|
|
||||||
# exempting rules (nobandlimin and friends) have to be listed first.
|
|
||||||
config_list_foreach global pcre append_pcre
|
|
||||||
config_list_foreach global limit append_limit
|
|
||||||
|
|
||||||
config_list_foreach global include append_include
|
|
||||||
config_list_foreach global extra_config append_line
|
|
||||||
|
|
||||||
[ -n "$maxconn" ] && echo "maxconn $maxconn" >> "$CFGFILE"
|
|
||||||
|
|
||||||
config_foreach append_service service
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
start_service() {
|
|
||||||
local enabled
|
|
||||||
|
|
||||||
config_load 3proxy
|
|
||||||
config_get_bool enabled global enabled 0
|
|
||||||
|
|
||||||
[ "$enabled" -gt 0 ] || {
|
|
||||||
echo "3proxy is disabled in /etc/config/3proxy" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
write_config
|
|
||||||
|
|
||||||
procd_open_instance
|
|
||||||
procd_set_param command "$PROG" "$CFGFILE"
|
|
||||||
procd_set_param file "$CFGFILE"
|
|
||||||
procd_set_param respawn
|
|
||||||
procd_set_param stdout 1
|
|
||||||
procd_set_param stderr 1
|
|
||||||
procd_close_instance
|
|
||||||
}
|
|
||||||
|
|
||||||
service_triggers() {
|
|
||||||
procd_add_reload_trigger "3proxy"
|
|
||||||
}
|
|
||||||
|
|
||||||
reload_service() {
|
|
||||||
stop
|
|
||||||
start
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user