mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-17 08:55:49 +08:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
371d8396b4 | ||
|
|
0f720bb44d | ||
|
|
3feb6df00d | ||
|
|
7e0ee5bace | ||
|
|
be619898c6 | ||
|
|
9d0dcaf63f | ||
|
|
a07665c01f | ||
|
|
3bd7cee5b7 | ||
|
|
b61ae3feac | ||
|
|
e6efa331b5 | ||
|
|
dd45805fce | ||
|
|
661631138a | ||
|
|
3422f780bf | ||
|
|
0df93bfab7 | ||
|
|
36979639b7 | ||
|
|
a11427afe9 | ||
|
|
d281b69209 | ||
|
|
a4ac85efc5 | ||
|
|
754ba7115a | ||
|
|
ff77d222e4 | ||
|
|
da99424eac | ||
|
|
95eb9f2a9f | ||
|
|
8fba7ffc40 | ||
|
|
b19e310956 | ||
|
|
34722c031f | ||
|
|
6c9c4d51aa | ||
|
|
a3605b8289 | ||
|
|
39bc8b065c | ||
|
|
63cc737b62 | ||
|
|
aeee37998e | ||
|
|
a830104238 | ||
|
|
b5e75daee4 | ||
|
|
db2f57fdd2 | ||
|
|
d53fdbc536 | ||
|
|
3dfd9052be | ||
|
|
8e2732b323 |
139
.github/workflows/build-ipk.yml
vendored
Normal file
139
.github/workflows/build-ipk.yml
vendored
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
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
|
||||||
159
.github/workflows/build-rpm-arm64.yml
vendored
159
.github/workflows/build-rpm-arm64.yml
vendored
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -22,7 +26,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pwd
|
pwd
|
||||||
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
|
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
|
||||||
echo "VERSION=$(date +%y%m%d%H%M%S)" >> $GITHUB_ENV
|
BUILDDATE=$(sed -n 's/^#define BUILDDATE "\(.*\)"$/\1/p' src/version.h)
|
||||||
|
[ -n "$BUILDDATE" ] || BUILDDATE=$(date -u +%y%m%d%H%M%S)
|
||||||
|
echo "VERSION=$BUILDDATE" >> $GITHUB_ENV
|
||||||
|
SOURCE_DATE_EPOCH=$(date -u -d "20${BUILDDATE:0:2}-${BUILDDATE:2:2}-${BUILDDATE:4:2} ${BUILDDATE:6:2}:${BUILDDATE:8:2}:${BUILDDATE:10:2}" +%s)
|
||||||
|
echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" >> $GITHUB_ENV
|
||||||
- name: echo env
|
- name: echo env
|
||||||
run: echo "release $RELEASE version $VERSION"
|
run: echo "release $RELEASE version $VERSION"
|
||||||
- name: Linux libraries
|
- name: Linux libraries
|
||||||
@ -39,45 +47,142 @@ jobs:
|
|||||||
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
|
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
|
||||||
- name: rpmbuild
|
- name: rpmbuild
|
||||||
run: |
|
run: |
|
||||||
ret=`pwd`
|
mkdir -p rpmout
|
||||||
cd ~/rpmbuild/SPECS
|
for EL in 8 9 10; do
|
||||||
rpmbuild -ba 3proxy-$RELEASE.spec
|
docker run --rm \
|
||||||
cd $ret
|
-v "$HOME/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz:/src.tar.gz:ro" \
|
||||||
mv ~/rpmbuild/RPMS/aarch64/3proxy-$RELEASE-1.aarch64.rpm 3proxy-$RELEASE.arm64.rpm
|
-v "$PWD/scripts/rh/3proxy.spec:/3proxy.spec:ro" \
|
||||||
|
-v "$PWD/rpmout:/out" \
|
||||||
|
-e RELEASE="$RELEASE" -e HOSTUID="$(id -u)" -e HOSTGID="$(id -g)" \
|
||||||
|
-e SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \
|
||||||
|
"almalinux:$EL" bash -c '
|
||||||
|
set -e
|
||||||
|
dnf -y install rpm-build gcc make openssl-devel pcre2-devel pam-devel tar gzip
|
||||||
|
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
|
cp /src.tar.gz ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz
|
||||||
|
ln -sf ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
|
||||||
|
cp /3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
|
||||||
|
cd ~/rpmbuild/SPECS
|
||||||
|
rpmbuild -ba \
|
||||||
|
--define "use_source_date_epoch_as_buildtime 1" \
|
||||||
|
--define "clamp_mtime_to_source_date_epoch 1" \
|
||||||
|
--define "_buildhost 3proxy.org" \
|
||||||
|
3proxy-$RELEASE.spec
|
||||||
|
cp ~/rpmbuild/RPMS/*/*.rpm /out/
|
||||||
|
chown "$HOSTUID:$HOSTGID" /out/*.rpm || chmod 0666 /out/*.rpm'
|
||||||
|
done
|
||||||
|
for f in rpmout/*.rpm; do
|
||||||
|
dist=$(rpm -qp --qf '%{RELEASE}' "$f" | sed 's/^1\.//')
|
||||||
|
arch=$(rpm -qp --qf '%{ARCH}' "$f")
|
||||||
|
mv "$f" "3proxy-$RELEASE.$dist.$arch.rpm"
|
||||||
|
done
|
||||||
|
rmdir rpmout
|
||||||
|
ls -l *.rpm
|
||||||
- name: Get artifact rpm
|
- name: Get artifact rpm
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: "3proxy-${{ env.RELEASE }}-arm64.rpm"
|
name: "3proxy-${{ env.RELEASE }}-arm64.rpm"
|
||||||
path: "*.rpm"
|
path: "*.rpm"
|
||||||
- name: Upload rpm to release
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm64.rpm
|
|
||||||
- name: debbuild
|
- name: debbuild
|
||||||
run: |
|
run: |
|
||||||
ret=`pwd`
|
docker run --rm \
|
||||||
cd ~/debian/
|
-v "$HOME/debian:/debian" \
|
||||||
tar xzf 3proxy_$RELEASE.orig.tar.gz
|
-e RELEASE="$RELEASE" -e VERSION="$VERSION" \
|
||||||
cd 3proxy-$RELEASE
|
-e SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \
|
||||||
echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium" >debian/changelog
|
ubuntu:22.04 bash -c '
|
||||||
echo " " >>debian/changelog
|
set -e
|
||||||
echo " *3proxy $RELEASE build" >>debian/changelog
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
echo " " >>debian/changelog
|
apt-get update
|
||||||
echo " -- z3APA3A <3apa3a@3proxy.org> "`date "+%a, %d %b %Y %H:%M:%S %z"` >>debian/changelog
|
apt-get install -y build-essential debhelper fakeroot libssl-dev libpcre2-dev libpam0g-dev
|
||||||
echo "">>debian/changelog
|
cd /debian
|
||||||
dpkg-buildpackage
|
tar xzf 3proxy_$RELEASE.orig.tar.gz
|
||||||
cd $ret
|
cd 3proxy-$RELEASE
|
||||||
|
{ echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium"
|
||||||
|
echo " "
|
||||||
|
echo " *3proxy $RELEASE build"
|
||||||
|
echo " "
|
||||||
|
echo " -- z3APA3A <3apa3a@3proxy.org> $(date -R -u -d @$SOURCE_DATE_EPOCH)"
|
||||||
|
echo ""
|
||||||
|
} > debian/changelog
|
||||||
|
dpkg-buildpackage'
|
||||||
cp ~/debian/3proxy_$RELEASE-"$VERSION"_arm64.deb ./3proxy-$RELEASE.arm64.deb
|
cp ~/debian/3proxy_$RELEASE-"$VERSION"_arm64.deb ./3proxy-$RELEASE.arm64.deb
|
||||||
- name: Get artifact deb
|
- name: Get artifact deb
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: "3proxy-${{ env.RELEASE }}-arm64.deb"
|
name: "3proxy-${{ env.RELEASE }}-arm64.deb"
|
||||||
path: "*.deb"
|
path: "*.deb"
|
||||||
- name: Upload deb to release
|
- 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: Sign rpm
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
run: |
|
||||||
|
GPGBIN=$(command -v gpg)
|
||||||
|
if [ -z "$GPGBIN" ]; then echo "gpg not found"; exit 1; fi
|
||||||
|
umask 077
|
||||||
|
printf '%s' "$GPG_PASSPHRASE" > /tmp/gpgpass
|
||||||
|
echo test > /tmp/signtest
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase-file /tmp/gpgpass \
|
||||||
|
-u "$GPG_KEYID" --detach-sign -o /tmp/signtest.sig /tmp/signtest
|
||||||
|
echo "key can sign"
|
||||||
|
{ echo "%_gpg_name $GPG_KEYID"
|
||||||
|
echo "%__gpg $GPGBIN"
|
||||||
|
echo '%__gpg_sign_cmd %{__gpg} gpg --batch --no-armor --pinentry-mode loopback --passphrase-file /tmp/gpgpass --no-secmem-warning --digest-algo sha256 -u "%{_gpg_name}" -sbo %{__signature_filename} %{__plaintext_filename}'
|
||||||
|
} > ~/.rpmmacros
|
||||||
|
rpm --addsign *.rpm
|
||||||
|
rm -f /tmp/gpgpass /tmp/signtest /tmp/signtest.sig
|
||||||
|
for f in *.rpm; do
|
||||||
|
sig=$(rpm -qp --qf '%{RSAHEADER:pgpsig}' "$f" 2>/dev/null)
|
||||||
|
case "$sig" in ""|"(none)")
|
||||||
|
sig=$(rpm -qp --qf '%{DSAHEADER:pgpsig}' "$f" 2>/dev/null) ;;
|
||||||
|
esac
|
||||||
|
case "$sig" in ""|"(none)")
|
||||||
|
echo "$f is not signed"
|
||||||
|
echo "--- rpm version ---"; rpm --version
|
||||||
|
echo "--- sign cmd ---"; rpm --eval '%{__gpg_sign_cmd}'
|
||||||
|
echo "--- secret keys ---"; gpg --list-secret-keys --with-colons | grep -E '^(sec|ssb):' || true
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
echo "$f: $sig"
|
||||||
|
done
|
||||||
|
- name: Checksums and detached signatures
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
run: |
|
||||||
|
sha256sum *.rpm *.deb > SHA256SUMS-arm64
|
||||||
|
for f in *.deb SHA256SUMS-arm64; do
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$GPG_KEYID" --armor --detach-sign "$f"
|
||||||
|
done
|
||||||
|
sha256sum -c SHA256SUMS-arm64
|
||||||
|
gpg --verify SHA256SUMS-arm64.asc SHA256SUMS-arm64
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.rpm
|
||||||
|
*.deb
|
||||||
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm64.deb
|
run: gh release upload "$TAG" *.rpm *.deb *.deb.asc SHA256SUMS-arm64 SHA256SUMS-arm64.asc
|
||||||
|
|||||||
153
.github/workflows/build-rpm-armhf.yml
vendored
153
.github/workflows/build-rpm-armhf.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: RPM/DEB build armhf
|
name: DEB build armhf
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -22,35 +26,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pwd
|
pwd
|
||||||
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
|
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
|
||||||
echo "VERSION=$(date +%y%m%d%H%M%S)" >> $GITHUB_ENV
|
BUILDDATE=$(sed -n 's/^#define BUILDDATE "\(.*\)"$/\1/p' src/version.h)
|
||||||
- name: Linux libraries
|
[ -n "$BUILDDATE" ] || BUILDDATE=$(date -u +%y%m%d%H%M%S)
|
||||||
run: |
|
echo "VERSION=$BUILDDATE" >> $GITHUB_ENV
|
||||||
sudo apt update
|
SOURCE_DATE_EPOCH=$(date -u -d "20${BUILDDATE:0:2}-${BUILDDATE:2:2}-${BUILDDATE:4:2} ${BUILDDATE:6:2}:${BUILDDATE:8:2}:${BUILDDATE:10:2}" +%s)
|
||||||
sudo dpkg --add-architecture armhf
|
echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" >> $GITHUB_ENV
|
||||||
echo "Types: deb" > ~/ubuntu.sources
|
- name: configure deb env
|
||||||
echo "URIs: http://archive.ubuntu.com/ubuntu/" >> ~/ubuntu.sources
|
|
||||||
echo "Suites: noble noble-updates noble-backports" >> ~/ubuntu.sources
|
|
||||||
echo "Components: main restricted universe multiverse" >> ~/ubuntu.sources
|
|
||||||
echo "Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" >> ~/ubuntu.sources
|
|
||||||
echo "Architectures: amd64" >> ~/ubuntu.sources
|
|
||||||
echo "" >> ~/ubuntu.sources
|
|
||||||
echo "Types: deb" >> ~/ubuntu.sources
|
|
||||||
echo "URIs: http://security.ubuntu.com/ubuntu/" >> ~/ubuntu.sources
|
|
||||||
echo "Suites: noble-security" >> ~/ubuntu.sources
|
|
||||||
echo "Components: main restricted universe multiverse" >> ~/ubuntu.sources
|
|
||||||
echo "Architectures: amd64" >> ~/ubuntu.sources
|
|
||||||
echo "Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" >> ~/ubuntu.sources
|
|
||||||
echo "" >> ~/ubuntu.sources
|
|
||||||
echo "Types: deb" >>~/ubuntu.sources
|
|
||||||
echo "URIs: http://ports.ubuntu.com/ubuntu-ports/" >>~/ubuntu.sources
|
|
||||||
echo "Suites: noble noble-updates" >>~/ubuntu.sources
|
|
||||||
echo "Components: main restricted universe multiverse" >>~/ubuntu.sources
|
|
||||||
echo "Architectures: armhf" >>~/ubuntu.sources
|
|
||||||
echo "Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" >>~/ubuntu.sources
|
|
||||||
sudo cp ~/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install libssl3t64:armhf openssl:armhf libssl-dev:armhf libpam0g:armhf libpam0g-dev:armhf libpcre2-dev:armhf rpm crossbuild-essential-armhf build-essential debhelper
|
|
||||||
- name: configure rpm env
|
|
||||||
run: |
|
run: |
|
||||||
mkdir ~/debian
|
mkdir ~/debian
|
||||||
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
@ -58,59 +39,81 @@ jobs:
|
|||||||
ln -s ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
|
ln -s ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
|
||||||
cp scripts/rh/3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
|
cp scripts/rh/3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
|
||||||
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
|
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
|
||||||
- name: rpmbuild
|
|
||||||
run: |
|
|
||||||
ret=`pwd`
|
|
||||||
cd ~/rpmbuild/SPECS
|
|
||||||
PATH=/usr/arm-linux-gnueabihf/bin:$PATH
|
|
||||||
export PATH=$PATH
|
|
||||||
CC=arm-linux-gnueabihf-gcc
|
|
||||||
export CC=$CC
|
|
||||||
export RPATH=/usr/arm-linux-gnueabihf/lib:$RPATH
|
|
||||||
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib:$LD_LIBRARY_PATH
|
|
||||||
rpmbuild -ba --define "PAMLIB pam0g" --define "_arch arm" --define "cross yes" --target=arm-linux-gnueabihf 3proxy-$RELEASE.spec
|
|
||||||
cd $ret
|
|
||||||
mv ~/rpmbuild/RPMS/arm/3proxy-$RELEASE-1.arm.rpm 3proxy-$RELEASE.arm.rpm
|
|
||||||
- name: Get artifact rpm
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
with:
|
|
||||||
name: "3proxy-${{ env.RELEASE }}-arm.rpm"
|
|
||||||
path: "*.rpm"
|
|
||||||
- name: Upload rpm to release
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm.rpm
|
|
||||||
- name: debbuild
|
- name: debbuild
|
||||||
run: |
|
run: |
|
||||||
ret=`pwd`
|
docker run --rm \
|
||||||
cd ~/debian/
|
-v "$HOME/debian:/debian" \
|
||||||
tar xzf 3proxy_$RELEASE.orig.tar.gz
|
-e RELEASE="$RELEASE" -e VERSION="$VERSION" \
|
||||||
cd 3proxy-$RELEASE
|
-e SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \
|
||||||
echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium" >debian/changelog
|
ubuntu:22.04 bash -c '
|
||||||
echo " " >>debian/changelog
|
set -e
|
||||||
echo " *3proxy $RELEASE build" >>debian/changelog
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
echo " " >>debian/changelog
|
dpkg --add-architecture armhf
|
||||||
echo " -- z3APA3A <3apa3a@3proxy.org> "`date "+%a, %d %b %Y %H:%M:%S %z"` >>debian/changelog
|
sed -i "s|^deb |deb [arch=amd64] |" /etc/apt/sources.list
|
||||||
echo "">>debian/changelog
|
{ echo "deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse"
|
||||||
PATH=/usr/arm-linux-gnueabihf/bin:$PATH
|
echo "deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse"
|
||||||
export PATH=$PATH
|
} >> /etc/apt/sources.list
|
||||||
CC=arm-linux-gnueabihf-gcc
|
apt-get update
|
||||||
export CC=$CC
|
apt-get install -y crossbuild-essential-armhf build-essential debhelper fakeroot \
|
||||||
export RPATH=/usr/arm-linux-gnueabihf/lib:$RPATH
|
libssl-dev:armhf libpcre2-dev:armhf libpam0g-dev:armhf
|
||||||
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib:$LD_LIBRARY_PATH
|
cd /debian
|
||||||
dpkg-buildpackage
|
tar xzf 3proxy_$RELEASE.orig.tar.gz
|
||||||
cd $ret
|
cd 3proxy-$RELEASE
|
||||||
|
{ echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium"
|
||||||
|
echo " "
|
||||||
|
echo " *3proxy $RELEASE build"
|
||||||
|
echo " "
|
||||||
|
echo " -- z3APA3A <3apa3a@3proxy.org> $(date -R -u -d @$SOURCE_DATE_EPOCH)"
|
||||||
|
echo ""
|
||||||
|
} > debian/changelog
|
||||||
|
export PATH=/usr/arm-linux-gnueabihf/bin:$PATH
|
||||||
|
export CC=arm-linux-gnueabihf-gcc
|
||||||
|
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib:$LD_LIBRARY_PATH
|
||||||
|
dpkg-buildpackage'
|
||||||
cp ~/debian/3proxy_$RELEASE-"$VERSION"_armhf.deb ./3proxy-$RELEASE.arm.deb
|
cp ~/debian/3proxy_$RELEASE-"$VERSION"_armhf.deb ./3proxy-$RELEASE.arm.deb
|
||||||
- name: Get artifact deb
|
- name: Get artifact deb
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: "3proxy-${{ env.RELEASE }}-arm.deb"
|
name: "3proxy-${{ env.RELEASE }}-arm.deb"
|
||||||
path: "*.deb"
|
path: "*.deb"
|
||||||
- name: Upload deb to release
|
- 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: |
|
||||||
|
sha256sum *.deb > SHA256SUMS-arm
|
||||||
|
for f in *.deb SHA256SUMS-arm; do
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$GPG_KEYID" --armor --detach-sign "$f"
|
||||||
|
done
|
||||||
|
sha256sum -c SHA256SUMS-arm
|
||||||
|
gpg --verify SHA256SUMS-arm.asc SHA256SUMS-arm
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.deb
|
||||||
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm.deb
|
run: gh release upload "$TAG" *.deb *.deb.asc SHA256SUMS-arm SHA256SUMS-arm.asc
|
||||||
|
|||||||
161
.github/workflows/build-rpm-x86-64.yml
vendored
161
.github/workflows/build-rpm-x86-64.yml
vendored
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -22,7 +26,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pwd
|
pwd
|
||||||
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
|
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
|
||||||
echo "VERSION=$(date +%y%m%d%H%M%S)" >> $GITHUB_ENV
|
BUILDDATE=$(sed -n 's/^#define BUILDDATE "\(.*\)"$/\1/p' src/version.h)
|
||||||
|
[ -n "$BUILDDATE" ] || BUILDDATE=$(date -u +%y%m%d%H%M%S)
|
||||||
|
echo "VERSION=$BUILDDATE" >> $GITHUB_ENV
|
||||||
|
SOURCE_DATE_EPOCH=$(date -u -d "20${BUILDDATE:0:2}-${BUILDDATE:2:2}-${BUILDDATE:4:2} ${BUILDDATE:6:2}:${BUILDDATE:8:2}:${BUILDDATE:10:2}" +%s)
|
||||||
|
echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" >> $GITHUB_ENV
|
||||||
- name: echo env
|
- name: echo env
|
||||||
run: echo "release $RELEASE version $VERSION"
|
run: echo "release $RELEASE version $VERSION"
|
||||||
- name: Linux libraries
|
- name: Linux libraries
|
||||||
@ -39,46 +47,143 @@ jobs:
|
|||||||
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
|
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
|
||||||
- name: rpmbuild
|
- name: rpmbuild
|
||||||
run: |
|
run: |
|
||||||
ret=`pwd`
|
mkdir -p rpmout
|
||||||
cd ~/rpmbuild/SPECS
|
for EL in 8 9 10; do
|
||||||
rpmbuild -ba 3proxy-$RELEASE.spec
|
docker run --rm \
|
||||||
cd $ret
|
-v "$HOME/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz:/src.tar.gz:ro" \
|
||||||
mv ~/rpmbuild/RPMS/x86_64/3proxy-$RELEASE-1.x86_64.rpm 3proxy-$RELEASE.x86_64.rpm
|
-v "$PWD/scripts/rh/3proxy.spec:/3proxy.spec:ro" \
|
||||||
|
-v "$PWD/rpmout:/out" \
|
||||||
|
-e RELEASE="$RELEASE" -e HOSTUID="$(id -u)" -e HOSTGID="$(id -g)" \
|
||||||
|
-e SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \
|
||||||
|
"almalinux:$EL" bash -c '
|
||||||
|
set -e
|
||||||
|
dnf -y install rpm-build gcc make openssl-devel pcre2-devel pam-devel tar gzip
|
||||||
|
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
|
cp /src.tar.gz ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz
|
||||||
|
ln -sf ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
|
||||||
|
cp /3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
|
||||||
|
cd ~/rpmbuild/SPECS
|
||||||
|
rpmbuild -ba \
|
||||||
|
--define "use_source_date_epoch_as_buildtime 1" \
|
||||||
|
--define "clamp_mtime_to_source_date_epoch 1" \
|
||||||
|
--define "_buildhost 3proxy.org" \
|
||||||
|
3proxy-$RELEASE.spec
|
||||||
|
cp ~/rpmbuild/RPMS/*/*.rpm /out/
|
||||||
|
chown "$HOSTUID:$HOSTGID" /out/*.rpm || chmod 0666 /out/*.rpm'
|
||||||
|
done
|
||||||
|
for f in rpmout/*.rpm; do
|
||||||
|
dist=$(rpm -qp --qf '%{RELEASE}' "$f" | sed 's/^1\.//')
|
||||||
|
arch=$(rpm -qp --qf '%{ARCH}' "$f")
|
||||||
|
mv "$f" "3proxy-$RELEASE.$dist.$arch.rpm"
|
||||||
|
done
|
||||||
|
rmdir rpmout
|
||||||
|
ls -l *.rpm
|
||||||
- name: Get artifact rpm
|
- name: Get artifact rpm
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: "3proxy-${{ env.RELEASE }}-x86_64.rpm"
|
name: "3proxy-${{ env.RELEASE }}-x86_64.rpm"
|
||||||
path: "*.rpm"
|
path: "*.rpm"
|
||||||
- name: Upload rpm to release
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.x86_64.rpm
|
|
||||||
- name: debbuild
|
- name: debbuild
|
||||||
run: |
|
run: |
|
||||||
ret=`pwd`
|
docker run --rm \
|
||||||
cd ~/debian/
|
-v "$HOME/debian:/debian" \
|
||||||
tar xzf 3proxy_$RELEASE.orig.tar.gz
|
-e RELEASE="$RELEASE" -e VERSION="$VERSION" \
|
||||||
cd 3proxy-$RELEASE
|
-e SOURCE_DATE_EPOCH="$SOURCE_DATE_EPOCH" \
|
||||||
echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium" >debian/changelog
|
ubuntu:22.04 bash -c '
|
||||||
echo " " >>debian/changelog
|
set -e
|
||||||
echo " *3proxy $RELEASE build" >>debian/changelog
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
echo " " >>debian/changelog
|
apt-get update
|
||||||
echo " -- z3APA3A <3apa3a@3proxy.org> "`date "+%a, %d %b %Y %H:%M:%S %z"` >>debian/changelog
|
apt-get install -y build-essential debhelper fakeroot libssl-dev libpcre2-dev libpam0g-dev
|
||||||
echo "">>debian/changelog
|
cd /debian
|
||||||
dpkg-buildpackage
|
tar xzf 3proxy_$RELEASE.orig.tar.gz
|
||||||
cd $ret
|
cd 3proxy-$RELEASE
|
||||||
|
{ echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium"
|
||||||
|
echo " "
|
||||||
|
echo " *3proxy $RELEASE build"
|
||||||
|
echo " "
|
||||||
|
echo " -- z3APA3A <3apa3a@3proxy.org> $(date -R -u -d @$SOURCE_DATE_EPOCH)"
|
||||||
|
echo ""
|
||||||
|
} > debian/changelog
|
||||||
|
dpkg-buildpackage'
|
||||||
cp ~/debian/3proxy_$RELEASE-"$VERSION"_amd64.deb ./3proxy-$RELEASE.x86_64.deb
|
cp ~/debian/3proxy_$RELEASE-"$VERSION"_amd64.deb ./3proxy-$RELEASE.x86_64.deb
|
||||||
- name: Get artifact deb
|
- name: Get artifact deb
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: "3proxy-${{ env.RELEASE }}-x86_64.deb"
|
name: "3proxy-${{ env.RELEASE }}-x86_64.deb"
|
||||||
path: "*.deb"
|
path: "*.deb"
|
||||||
- name: Upload deb to release
|
|
||||||
|
- 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: Sign rpm
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
run: |
|
||||||
|
GPGBIN=$(command -v gpg)
|
||||||
|
if [ -z "$GPGBIN" ]; then echo "gpg not found"; exit 1; fi
|
||||||
|
umask 077
|
||||||
|
printf '%s' "$GPG_PASSPHRASE" > /tmp/gpgpass
|
||||||
|
echo test > /tmp/signtest
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase-file /tmp/gpgpass \
|
||||||
|
-u "$GPG_KEYID" --detach-sign -o /tmp/signtest.sig /tmp/signtest
|
||||||
|
echo "key can sign"
|
||||||
|
{ echo "%_gpg_name $GPG_KEYID"
|
||||||
|
echo "%__gpg $GPGBIN"
|
||||||
|
echo '%__gpg_sign_cmd %{__gpg} gpg --batch --no-armor --pinentry-mode loopback --passphrase-file /tmp/gpgpass --no-secmem-warning --digest-algo sha256 -u "%{_gpg_name}" -sbo %{__signature_filename} %{__plaintext_filename}'
|
||||||
|
} > ~/.rpmmacros
|
||||||
|
rpm --addsign *.rpm
|
||||||
|
rm -f /tmp/gpgpass /tmp/signtest /tmp/signtest.sig
|
||||||
|
for f in *.rpm; do
|
||||||
|
sig=$(rpm -qp --qf '%{RSAHEADER:pgpsig}' "$f" 2>/dev/null)
|
||||||
|
case "$sig" in ""|"(none)")
|
||||||
|
sig=$(rpm -qp --qf '%{DSAHEADER:pgpsig}' "$f" 2>/dev/null) ;;
|
||||||
|
esac
|
||||||
|
case "$sig" in ""|"(none)")
|
||||||
|
echo "$f is not signed"
|
||||||
|
echo "--- rpm version ---"; rpm --version
|
||||||
|
echo "--- sign cmd ---"; rpm --eval '%{__gpg_sign_cmd}'
|
||||||
|
echo "--- secret keys ---"; gpg --list-secret-keys --with-colons | grep -E '^(sec|ssb):' || true
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
echo "$f: $sig"
|
||||||
|
done
|
||||||
|
- name: Checksums and detached signatures
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
run: |
|
||||||
|
sha256sum *.rpm *.deb > SHA256SUMS-x86_64
|
||||||
|
for f in *.deb SHA256SUMS-x86_64; do
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$GPG_KEYID" --armor --detach-sign "$f"
|
||||||
|
done
|
||||||
|
sha256sum -c SHA256SUMS-x86_64
|
||||||
|
gpg --verify SHA256SUMS-x86_64.asc SHA256SUMS-x86_64
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.rpm
|
||||||
|
*.deb
|
||||||
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.x86_64.deb
|
run: gh release upload "$TAG" *.rpm *.deb *.deb.asc SHA256SUMS-x86_64 SHA256SUMS-x86_64.asc
|
||||||
|
|
||||||
|
|||||||
41
.github/workflows/build-watcom.yml
vendored
41
.github/workflows/build-watcom.yml
vendored
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -34,19 +38,8 @@ jobs:
|
|||||||
- name: make Watcom
|
- name: make Watcom
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
|
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\n^";" >>src/3proxy.c
|
||||||
nmake /F Makefile.watcom
|
nmake /F Makefile.watcom
|
||||||
- name: Decode Certificate
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
|
|
||||||
- name: Sign
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$signtool = (Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" | Sort-Object { [version]$_.Directory.Parent.Name } -Descending | Select-Object -First 1).FullName
|
|
||||||
& $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "bin\3proxy.exe"
|
|
||||||
& $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "bin\3proxy_crypt.exe"
|
|
||||||
- name: make dist dir
|
- name: make dist dir
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -86,10 +79,30 @@ jobs:
|
|||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-lite.zip
|
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-lite.zip
|
||||||
|
- name: Checksums and detached signature
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
shell: bash
|
||||||
|
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
|
||||||
|
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
|
||||||
|
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
|
||||||
|
sha256sum *.zip > SHA256SUMS-win-lite
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-lite
|
||||||
|
sha256sum -c SHA256SUMS-win-lite
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.zip
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-lite.zip
|
run: gh release upload "$TAG" *.zip SHA256SUMS-win-lite SHA256SUMS-win-lite.asc
|
||||||
|
|||||||
50
.github/workflows/build-win32.yml
vendored
50
.github/workflows/build-win32.yml
vendored
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -40,27 +44,8 @@ jobs:
|
|||||||
cd "D:/a/3proxy/3proxy"
|
cd "D:/a/3proxy/3proxy"
|
||||||
set "LIB=%LIB%;c:/vcpkg/installed/x86-windows-static/lib"
|
set "LIB=%LIB%;c:/vcpkg/installed/x86-windows-static/lib"
|
||||||
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x86-windows-static/include"
|
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x86-windows-static/include"
|
||||||
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
|
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\n^";" >>src/3proxy.c
|
||||||
nmake /F Makefile.msvc WOLFSSL=1
|
nmake /F Makefile.msvc WOLFSSL=1
|
||||||
- name: Decode Certificate
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
|
|
||||||
- name: Extract public certificate
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${{ github.workspace }}\cert.pfx", "$env:CERT_PASSWORD")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\3proxy.crt", $cert.Export("Cert"))
|
|
||||||
- name: Sign
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
$signtool = (Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" | Sort-Object { [version]$_.Directory.Parent.Name } -Descending | Select-Object -First 1).FullName
|
|
||||||
Get-ChildItem bin\*.exe, bin\*.dll | ForEach-Object { & $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "$env:CERT_PASSWORD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 $_.FullName }
|
|
||||||
- name: make dist dir
|
- name: make dist dir
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -91,7 +76,6 @@ jobs:
|
|||||||
copy authors dist\3proxy\
|
copy authors dist\3proxy\
|
||||||
copy README.md dist\3proxy\
|
copy README.md dist\3proxy\
|
||||||
copy rus.3ps dist\3proxy\
|
copy rus.3ps dist\3proxy\
|
||||||
copy 3proxy.crt dist\3proxy\
|
|
||||||
- name: Get artifact
|
- name: Get artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
@ -101,10 +85,30 @@ jobs:
|
|||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x86.zip
|
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x86.zip
|
||||||
|
- name: Checksums and detached signature
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
shell: bash
|
||||||
|
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
|
||||||
|
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
|
||||||
|
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
|
||||||
|
sha256sum *.zip > SHA256SUMS-win-x86
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-x86
|
||||||
|
sha256sum -c SHA256SUMS-win-x86
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.zip
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-x86.zip
|
run: gh release upload "$TAG" *.zip SHA256SUMS-win-x86 SHA256SUMS-win-x86.asc
|
||||||
|
|||||||
50
.github/workflows/build-win64.yml
vendored
50
.github/workflows/build-win64.yml
vendored
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -40,28 +44,9 @@ jobs:
|
|||||||
cd "D:/a/3proxy/3proxy"
|
cd "D:/a/3proxy/3proxy"
|
||||||
set "LIB=%LIB%;c:/vcpkg/installed/x64-windows-static/lib"
|
set "LIB=%LIB%;c:/vcpkg/installed/x64-windows-static/lib"
|
||||||
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x64-windows-static/include"
|
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/x64-windows-static/include"
|
||||||
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
|
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\n^";" >>src/3proxy.c
|
||||||
echo %NOW% / %RELEASE% / %BUILDDATE% / %VERSION%
|
echo %NOW% / %RELEASE% / %BUILDDATE% / %VERSION%
|
||||||
nmake /F Makefile.msvc WOLFSSL=1
|
nmake /F Makefile.msvc WOLFSSL=1
|
||||||
- name: Decode Certificate
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
|
|
||||||
- name: Extract public certificate
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${{ github.workspace }}\cert.pfx", "$env:CERT_PASSWORD")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\3proxy.crt", $cert.Export("Cert"))
|
|
||||||
- name: Sign
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
$signtool = (Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" | Sort-Object { [version]$_.Directory.Parent.Name } -Descending | Select-Object -First 1).FullName
|
|
||||||
Get-ChildItem bin\*.exe, bin\*.dll | ForEach-Object { & $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "$env:CERT_PASSWORD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 $_.FullName }
|
|
||||||
- name: make dist dir
|
- name: make dist dir
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -92,7 +77,6 @@ jobs:
|
|||||||
copy authors dist\3proxy\
|
copy authors dist\3proxy\
|
||||||
copy README.md dist\3proxy\
|
copy README.md dist\3proxy\
|
||||||
copy rus.3ps dist\3proxy\
|
copy rus.3ps dist\3proxy\
|
||||||
copy 3proxy.crt dist\3proxy\
|
|
||||||
- name: Get artifact
|
- name: Get artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
@ -102,10 +86,30 @@ jobs:
|
|||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x64.zip
|
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x64.zip
|
||||||
|
- name: Checksums and detached signature
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
shell: bash
|
||||||
|
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
|
||||||
|
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
|
||||||
|
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
|
||||||
|
sha256sum *.zip > SHA256SUMS-win-x64
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-x64
|
||||||
|
sha256sum -c SHA256SUMS-win-x64
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.zip
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-x64.zip
|
run: gh release upload "$TAG" *.zip SHA256SUMS-win-x64 SHA256SUMS-win-x64.asc
|
||||||
|
|||||||
50
.github/workflows/build-winarm64.yml
vendored
50
.github/workflows/build-winarm64.yml
vendored
@ -6,10 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
name: "${{ matrix.target }}"
|
name: "${{ matrix.target }}"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -40,27 +44,8 @@ jobs:
|
|||||||
cd "D:/a/3proxy/3proxy"
|
cd "D:/a/3proxy/3proxy"
|
||||||
set "LIB=%LIB%;c:/vcpkg/installed/arm64-windows-static/lib"
|
set "LIB=%LIB%;c:/vcpkg/installed/arm64-windows-static/lib"
|
||||||
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/arm64-windows-static/include"
|
set "INCLUDE=%INCLUDE%;c:/vcpkg/installed/arm64-windows-static/include"
|
||||||
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
|
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\n^";" >>src/3proxy.c
|
||||||
nmake /F Makefile.msvc WOLFSSL=1
|
nmake /F Makefile.msvc WOLFSSL=1
|
||||||
- name: Decode Certificate
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
|
|
||||||
- name: Extract public certificate
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${{ github.workspace }}\cert.pfx", "$env:CERT_PASSWORD")
|
|
||||||
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\3proxy.crt", $cert.Export("Cert"))
|
|
||||||
- name: Sign
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
$signtool = (Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" | Sort-Object { [version]$_.Directory.Parent.Name } -Descending | Select-Object -First 1).FullName
|
|
||||||
Get-ChildItem bin\*.exe, bin\*.dll | ForEach-Object { & $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "$env:CERT_PASSWORD" /tr http://timestamp.digicert.com /td sha256 /fd sha256 $_.FullName }
|
|
||||||
- name: make dist dir
|
- name: make dist dir
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -91,7 +76,6 @@ jobs:
|
|||||||
copy authors dist\3proxy\
|
copy authors dist\3proxy\
|
||||||
copy README.md dist\3proxy\
|
copy README.md dist\3proxy\
|
||||||
copy rus.3ps dist\3proxy\
|
copy rus.3ps dist\3proxy\
|
||||||
copy 3proxy.crt dist\3proxy\
|
|
||||||
- name: Get artifact
|
- name: Get artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
@ -101,10 +85,30 @@ jobs:
|
|||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-arm64.zip
|
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-arm64.zip
|
||||||
|
- name: Checksums and detached signature
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
shell: bash
|
||||||
|
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
|
||||||
|
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
|
||||||
|
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
|
||||||
|
sha256sum *.zip > SHA256SUMS-win-arm64
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-arm64
|
||||||
|
sha256sum -c SHA256SUMS-win-arm64
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.zip
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
TAG: ${{ github.event.release.tag_name }}
|
TAG: ${{ github.event.release.tag_name }}
|
||||||
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-arm64.zip
|
run: gh release upload "$TAG" *.zip SHA256SUMS-win-arm64 SHA256SUMS-win-arm64.asc
|
||||||
|
|||||||
99
.github/workflows/docker-ghcr.yml
vendored
99
.github/workflows/docker-ghcr.yml
vendored
@ -1,99 +0,0 @@
|
|||||||
name: Build Docker images (GHCR)
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build and push Docker images
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v7
|
|
||||||
|
|
||||||
- name: Determine tags
|
|
||||||
id: tags
|
|
||||||
env:
|
|
||||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
||||||
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
run: |
|
|
||||||
if [[ "$RELEASE_TAG" != "" ]]; then
|
|
||||||
RELEASE="${RELEASE_TAG#v}"
|
|
||||||
echo "minimal=${IMAGE}:${RELEASE}.minimal,${IMAGE}:minimal" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "busybox=${IMAGE}:${RELEASE}.busybox,${IMAGE}:busybox" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "full=${IMAGE}:${RELEASE},${IMAGE}:latest" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
DATETIME=$(date +%d%m%y%H%M%S)
|
|
||||||
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
|
|
||||||
echo "minimal=${IMAGE}:${DATETIME}-${BRANCH}.minimal,${IMAGE}:${BRANCH}.minimal" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "busybox=${IMAGE}:${DATETIME}-${BRANCH}.busybox,${IMAGE}:${BRANCH}.busybox" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "full=${IMAGE}:${DATETIME}-${BRANCH},${IMAGE}:${BRANCH}" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v4
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v4
|
|
||||||
|
|
||||||
- name: Install cosign
|
|
||||||
uses: sigstore/cosign-installer@v3
|
|
||||||
|
|
||||||
- name: Login to GHCR
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: docker/login-action@v4
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push minimal
|
|
||||||
uses: docker/build-push-action@v7
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Dockerfile.minimal
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.tags.outputs.minimal }}
|
|
||||||
|
|
||||||
- name: Build and push busybox
|
|
||||||
uses: docker/build-push-action@v7
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Dockerfile.busybox
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.tags.outputs.busybox }}
|
|
||||||
|
|
||||||
- name: Build and push full
|
|
||||||
uses: docker/build-push-action@v7
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Dockerfile.full
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.tags.outputs.full }}
|
|
||||||
|
|
||||||
- name: Sign images
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
env:
|
|
||||||
TAGS_MINIMAL: ${{ steps.tags.outputs.minimal }}
|
|
||||||
TAGS_BUSYBOX: ${{ steps.tags.outputs.busybox }}
|
|
||||||
TAGS_FULL: ${{ steps.tags.outputs.full }}
|
|
||||||
run: |
|
|
||||||
IFS=',' read -ra TAGS <<< "$TAGS_MINIMAL,$TAGS_BUSYBOX,$TAGS_FULL"
|
|
||||||
for tag in "${TAGS[@]}"; do
|
|
||||||
cosign sign --yes "$tag"
|
|
||||||
done
|
|
||||||
|
|
||||||
206
.github/workflows/docker.yml
vendored
206
.github/workflows/docker.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Build Docker images (Docker Hub)
|
name: Build Docker images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
@ -7,89 +7,187 @@ on:
|
|||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
id-token: write
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: docker.io
|
DOCKERHUB_IMAGE: docker.io/3proxy/3proxy
|
||||||
IMAGE_NAME: 3proxy/3proxy
|
GHCR_IMAGE: ghcr.io/3proxy/3proxy
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build and push Docker images
|
name: ${{ matrix.image }} ${{ matrix.platform }}
|
||||||
runs-on: ubuntu-latest
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
runs-on: ${{ matrix.runner }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
image: [full, busybox, minimal]
|
||||||
|
platform: [linux/amd64, linux/arm64, linux/arm/v7]
|
||||||
|
include:
|
||||||
|
- platform: linux/amd64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
- platform: linux/arm64
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
|
- platform: linux/arm/v7
|
||||||
|
runner: ubuntu-24.04-arm
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v7
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Determine tags
|
- name: Platform name
|
||||||
id: tags
|
id: platform
|
||||||
env:
|
run: echo "pair=$(echo '${{ matrix.platform }}' | tr / -)" >> "$GITHUB_OUTPUT"
|
||||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
||||||
run: |
|
|
||||||
if [[ "$RELEASE_TAG" != "" ]]; then
|
|
||||||
RELEASE="${RELEASE_TAG#v}"
|
|
||||||
echo "minimal=${REGISTRY}/${IMAGE_NAME}:${RELEASE}.minimal,${REGISTRY}/${IMAGE_NAME}:minimal" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "busybox=${REGISTRY}/${IMAGE_NAME}:${RELEASE}.busybox,${REGISTRY}/${IMAGE_NAME}:busybox" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "full=${REGISTRY}/${IMAGE_NAME}:${RELEASE},${REGISTRY}/${IMAGE_NAME}:latest" >> "$GITHUB_OUTPUT"
|
|
||||||
else
|
|
||||||
DATETIME=$(date +%d%m%y%H%M%S)
|
|
||||||
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
|
|
||||||
echo "minimal=${REGISTRY}/${IMAGE_NAME}:${DATETIME}-${BRANCH}.minimal,${REGISTRY}/${IMAGE_NAME}:${BRANCH}.minimal" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "busybox=${REGISTRY}/${IMAGE_NAME}:${DATETIME}-${BRANCH}.busybox,${REGISTRY}/${IMAGE_NAME}:${BRANCH}.busybox" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "full=${REGISTRY}/${IMAGE_NAME}:${DATETIME}-${BRANCH},${REGISTRY}/${IMAGE_NAME}:${BRANCH}" >> "$GITHUB_OUTPUT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
|
if: matrix.platform == 'linux/arm/v7'
|
||||||
uses: docker/setup-qemu-action@v4
|
uses: docker/setup-qemu-action@v4
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v4
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v4
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push by digest
|
||||||
|
id: build
|
||||||
|
uses: docker/build-push-action@v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Dockerfile.${{ matrix.image }}
|
||||||
|
platforms: ${{ matrix.platform }}
|
||||||
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||||
|
|
||||||
|
- name: Export digest
|
||||||
|
env:
|
||||||
|
DIGEST: ${{ steps.build.outputs.digest }}
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/digests
|
||||||
|
touch "/tmp/digests/${DIGEST#sha256:}"
|
||||||
|
|
||||||
|
- name: Upload digest
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: digests-${{ matrix.image }}-${{ steps.platform.outputs.pair }}
|
||||||
|
path: /tmp/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
publish:
|
||||||
|
name: Publish ${{ matrix.image }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- image: full
|
||||||
|
suffix: ''
|
||||||
|
floating: lts
|
||||||
|
- image: busybox
|
||||||
|
suffix: .busybox
|
||||||
|
floating: lts-busybox
|
||||||
|
- image: minimal
|
||||||
|
suffix: .minimal
|
||||||
|
floating: lts-minimal
|
||||||
|
steps:
|
||||||
|
- name: Download digests
|
||||||
|
uses: actions/download-artifact@v7
|
||||||
|
with:
|
||||||
|
path: /tmp/digests
|
||||||
|
pattern: digests-${{ matrix.image }}-*
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Install cosign
|
- name: Install cosign
|
||||||
uses: sigstore/cosign-installer@v3
|
uses: sigstore/cosign-installer@v3
|
||||||
|
with:
|
||||||
|
cosign-release: v2.4.3
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
uses: docker/login-action@v4
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push minimal
|
- name: Login to GHCR
|
||||||
uses: docker/build-push-action@v7
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
context: .
|
registry: ghcr.io
|
||||||
file: Dockerfile.minimal
|
username: ${{ github.actor }}
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.tags.outputs.minimal }}
|
|
||||||
|
|
||||||
- name: Build and push busybox
|
- name: Determine tags
|
||||||
uses: docker/build-push-action@v7
|
id: tags
|
||||||
with:
|
env:
|
||||||
context: .
|
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||||
file: Dockerfile.busybox
|
SUFFIX: ${{ matrix.suffix }}
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
|
FLOATING: ${{ matrix.floating }}
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
run: |
|
||||||
tags: ${{ steps.tags.outputs.busybox }}
|
if [[ "$RELEASE_TAG" != "" ]]; then
|
||||||
|
RELEASE="${RELEASE_TAG#v}"
|
||||||
|
echo "versioned=${RELEASE}${SUFFIX}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "moving=${FLOATING}" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
DATETIME=$(date +%d%m%y%H%M%S)
|
||||||
|
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
|
||||||
|
echo "versioned=${DATETIME}-${BRANCH}${SUFFIX}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "moving=${BRANCH}${SUFFIX}" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Build and push full
|
- name: Create manifest list and push
|
||||||
uses: docker/build-push-action@v7
|
working-directory: /tmp/digests
|
||||||
|
env:
|
||||||
|
VERSIONED: ${{ steps.tags.outputs.versioned }}
|
||||||
|
MOVING: ${{ steps.tags.outputs.moving }}
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools create \
|
||||||
|
-t "${DOCKERHUB_IMAGE}:${VERSIONED}" \
|
||||||
|
-t "${DOCKERHUB_IMAGE}:${MOVING}" \
|
||||||
|
-t "${GHCR_IMAGE}:${VERSIONED}" \
|
||||||
|
-t "${GHCR_IMAGE}:${MOVING}" \
|
||||||
|
$(printf "${GHCR_IMAGE}@sha256:%s " *)
|
||||||
|
|
||||||
|
- name: Get pushed digest
|
||||||
|
id: digest
|
||||||
|
env:
|
||||||
|
VERSIONED: ${{ steps.tags.outputs.versioned }}
|
||||||
|
run: |
|
||||||
|
DIGEST=$(docker buildx imagetools inspect "${DOCKERHUB_IMAGE}:${VERSIONED}" \
|
||||||
|
--format '{{json .Manifest}}' | jq -r .digest)
|
||||||
|
echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Attest Docker Hub image
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
with:
|
with:
|
||||||
context: .
|
subject-name: ${{ env.DOCKERHUB_IMAGE }}
|
||||||
file: Dockerfile.full
|
subject-digest: ${{ steps.digest.outputs.digest }}
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
|
push-to-registry: false
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.tags.outputs.full }}
|
- name: Attest GHCR image
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-name: ${{ env.GHCR_IMAGE }}
|
||||||
|
subject-digest: ${{ steps.digest.outputs.digest }}
|
||||||
|
push-to-registry: false
|
||||||
|
|
||||||
- name: Sign images
|
- name: Sign images
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
env:
|
env:
|
||||||
TAGS_MINIMAL: ${{ steps.tags.outputs.minimal }}
|
DIGEST: ${{ steps.digest.outputs.digest }}
|
||||||
TAGS_BUSYBOX: ${{ steps.tags.outputs.busybox }}
|
|
||||||
TAGS_FULL: ${{ steps.tags.outputs.full }}
|
|
||||||
run: |
|
run: |
|
||||||
IFS=',' read -ra TAGS <<< "$TAGS_MINIMAL,$TAGS_BUSYBOX,$TAGS_FULL"
|
cosign sign --yes "${DOCKERHUB_IMAGE}@${DIGEST}"
|
||||||
for tag in "${TAGS[@]}"; do
|
cosign sign --yes "${GHCR_IMAGE}@${DIGEST}"
|
||||||
cosign sign --yes "$tag"
|
|
||||||
done
|
|
||||||
|
|||||||
85
.github/workflows/release-tarball.yml
vendored
Normal file
85
.github/workflows/release-tarball.yml
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
name: Release source tarball
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tarball:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
name: "source tarball"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
|
- name: env
|
||||||
|
run: |
|
||||||
|
if [ -f RELEASE ]; then
|
||||||
|
RELEASE=$(tr -d ' \t\r\n' < RELEASE)
|
||||||
|
else
|
||||||
|
RELEASE=$(tr -d ' \t\r\n' < DEVEL)
|
||||||
|
fi
|
||||||
|
echo "RELEASE=$RELEASE" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create tarball
|
||||||
|
run: |
|
||||||
|
# git archive is reproducible from the tag: anyone can regenerate the
|
||||||
|
# tarball and compare it against the published checksum.
|
||||||
|
git archive --format=tar.gz -9 \
|
||||||
|
--prefix="3proxy-${{ env.RELEASE }}/" \
|
||||||
|
-o "3proxy-${{ env.RELEASE }}.tar.gz" HEAD
|
||||||
|
tar tzf "3proxy-${{ env.RELEASE }}.tar.gz" >/dev/null
|
||||||
|
ls -l *.tar.gz
|
||||||
|
|
||||||
|
- name: Get artifact
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: "3proxy-${{ env.RELEASE }}-src"
|
||||||
|
path: "*.tar.gz"
|
||||||
|
|
||||||
|
- name: Import signing key
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
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\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
|
||||||
|
|
||||||
|
- name: Checksums and detached signatures
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
env:
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
run: |
|
||||||
|
sha256sum *.tar.gz > SHA256SUMS-src
|
||||||
|
for f in *.tar.gz SHA256SUMS-src; do
|
||||||
|
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
|
||||||
|
-u "$GPG_KEYID" --armor --detach-sign "$f"
|
||||||
|
done
|
||||||
|
sha256sum -c SHA256SUMS-src
|
||||||
|
gpg --verify SHA256SUMS-src.asc SHA256SUMS-src
|
||||||
|
|
||||||
|
- name: Attest build provenance
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: actions/attest-build-provenance@v4
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
*.tar.gz
|
||||||
|
|
||||||
|
- 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" *.tar.gz *.tar.gz.asc SHA256SUMS-src SHA256SUMS-src.asc
|
||||||
94
.github/workflows/update-version.yml
vendored
Normal file
94
.github/workflows/update-version.yml
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
name: Update version files
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- RELEASE
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
version:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
|
- name: Regenerate version files
|
||||||
|
run: |
|
||||||
|
RELEASE=$(tr -d ' \t\r\n' < RELEASE)
|
||||||
|
if [ -z "$RELEASE" ]; then echo "RELEASE is empty"; exit 1; fi
|
||||||
|
MAJOR=$(echo "$RELEASE" | cut -d . -f 1)
|
||||||
|
SUBMAJOR=$(echo "$RELEASE" | cut -d . -f 2)
|
||||||
|
MINOR=$(echo "$RELEASE" | cut -d . -f 3)
|
||||||
|
SUBMINOR=$(echo "$RELEASE" | cut -d . -f 4)
|
||||||
|
[ -n "$SUBMAJOR" ] || SUBMAJOR=0
|
||||||
|
[ -n "$MINOR" ] || MINOR=0
|
||||||
|
[ -n "$SUBMINOR" ] || SUBMINOR=0
|
||||||
|
|
||||||
|
# The build date is minted once per release and then carried in
|
||||||
|
# version.h, so that rebuilding the same commit yields the same
|
||||||
|
# version string and the same package names.
|
||||||
|
OLDRELEASE=$(sed -n 's/^#define VERSION "3proxy-\(.*\)"$/\1/p' src/version.h 2>/dev/null)
|
||||||
|
OLDBUILDDATE=$(sed -n 's/^#define BUILDDATE "\(.*\)"$/\1/p' src/version.h 2>/dev/null)
|
||||||
|
if [ "$OLDRELEASE" = "$RELEASE" ] && [ -n "$OLDBUILDDATE" ]; then
|
||||||
|
BUILDDATE="$OLDBUILDDATE"
|
||||||
|
else
|
||||||
|
BUILDDATE=$(date -u +%y%m%d%H%M%S)
|
||||||
|
fi
|
||||||
|
echo "release $RELEASE -> $MAJOR $SUBMAJOR $MINOR $SUBMINOR, build date $BUILDDATE"
|
||||||
|
SOURCE_DATE_EPOCH=$(date -u -d "20${BUILDDATE:0:2}-${BUILDDATE:2:2}-${BUILDDATE:4:2} ${BUILDDATE:6:2}:${BUILDDATE:8:2}:${BUILDDATE:10:2}" +%s)
|
||||||
|
YEAR=$(date -u -d @$SOURCE_DATE_EPOCH +%Y)
|
||||||
|
|
||||||
|
DEBVERSION=$(head -1 debian/changelog | cut -d "(" -f 2 | cut -d ")" -f 1)
|
||||||
|
if [ "$DEBVERSION" != "$RELEASE-1" ]; then
|
||||||
|
mv debian/changelog debian/changelog.old
|
||||||
|
{ echo "3proxy ($RELEASE-1) buster; urgency=medium"
|
||||||
|
echo ""
|
||||||
|
echo " *3proxy $RELEASE initial build"
|
||||||
|
echo ""
|
||||||
|
echo " -- z3APA3A <3apa3a@3proxy.org> $(date -R -u -d @$SOURCE_DATE_EPOCH)"
|
||||||
|
echo ""
|
||||||
|
cat debian/changelog.old
|
||||||
|
} > debian/changelog
|
||||||
|
rm -f debian/changelog.old
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv scripts/rh/3proxy.spec scripts/rh/3proxy.spec.old
|
||||||
|
{ echo "Name: 3proxy"
|
||||||
|
echo "Version: $RELEASE"
|
||||||
|
echo "Release: 1%{?dist}"
|
||||||
|
tail --lines=+4 scripts/rh/3proxy.spec.old
|
||||||
|
} > scripts/rh/3proxy.spec
|
||||||
|
rm -f scripts/rh/3proxy.spec.old
|
||||||
|
|
||||||
|
{ echo "#ifndef VERSION"
|
||||||
|
echo "#define VERSION \"3proxy-$RELEASE\""
|
||||||
|
echo "#endif"
|
||||||
|
echo "#ifndef BUILDDATE"
|
||||||
|
echo "#define BUILDDATE \"$BUILDDATE\""
|
||||||
|
echo "#endif"
|
||||||
|
echo "#define MAJOR3PROXY $MAJOR"
|
||||||
|
echo "#define SUBMAJOR3PROXY $SUBMAJOR"
|
||||||
|
echo "#define MINOR3PROXY $MINOR"
|
||||||
|
echo "#define SUBMINOR3PROXY $SUBMINOR"
|
||||||
|
echo "#define RELEASE3PROXY \"3proxy-$RELEASE(\" BUILDDATE \")\\0\""
|
||||||
|
echo "#ifndef YEAR3PROXY"
|
||||||
|
echo "#define YEAR3PROXY \"$YEAR\""
|
||||||
|
echo "#endif"
|
||||||
|
} > src/version.h
|
||||||
|
|
||||||
|
- name: Commit
|
||||||
|
run: |
|
||||||
|
if [ -z "$(git status --porcelain debian/changelog scripts/rh/3proxy.spec src/version.h)" ]; then
|
||||||
|
echo "version files already up to date"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add debian/changelog scripts/rh/3proxy.spec src/version.h
|
||||||
|
git commit -m "Update version files for $(tr -d ' \t\r\n' < RELEASE)"
|
||||||
|
git push
|
||||||
29
3proxy-release-key.asc
Normal file
29
3proxy-release-key.asc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mQINBGqIZCIBEADF3zxdMo2dvUGAlQm3aIcQiqmpLMHucvLfSK3fHtwagO8f03CO
|
||||||
|
bEx9EfIK/U6BzLwEJ0CxyClzfvgo9COVpi5EjES9sI2LXzcgc4hGaYO0Q4Unj//0
|
||||||
|
W/G8aarDaLF2NRKMLf07eaYGBRJjqHnmeHgOHdr+SnN0JtMSadWMHoliB8esnabz
|
||||||
|
5CO4JabTrhwoez3DMLSgJNIod7wL6PJJv/2BeRahwNr2CjaXmzZKr/j7fc1MKLij
|
||||||
|
bsvJ5OmLmngZr6CHDa9cBhVhiH+7RgWLCsRlEGxEv7w0afp/T0xDwNAPkGzk5ObC
|
||||||
|
BrdXvypTAbNyUoVT8qSVJwkneZ4S0Ts4rRRNfNpaus4tsCmgyGKzsrbxvbiBOTPW
|
||||||
|
jB/fjkgr6X9M/AQ3yGpXrwXRJrM/nSfjUyOEHXttTC9HpGt41NH/mpC4mDWa1Kxi
|
||||||
|
FMxuo1+dw2kpDKl0Bp78IGdCo5akHwftFr8aHgmfZoGXAGJRHPAWbJGjC2ARy8yp
|
||||||
|
QOpxba0S3VlCU6bs8MDKl6cpWItnlXcl/GD/Qc55bjLXjFv1pbn2RUSYZS+n9wDX
|
||||||
|
64syZf3dZ/N5U4ydmybWfiLFUXqKQLtdO8QAWQGt4TSwKptTmI581/MMCTQ8qWZL
|
||||||
|
zgFj6C/8K0SZ4lMOv+5zfc2+QOoWw7E2Ws3stEKTyWjOMm/QMJAGumqvqwARAQAB
|
||||||
|
tCozcHJveHkgcmVsZWFzZSBzaWduaW5nIDwzcHJveHlAM3Byb3h5Lm9yZz6JAm0E
|
||||||
|
EwEIAFcWIQT8EiFEmfzHuhz/bNwDEjhOOnOUCwUCaohkIhsUgAAAAAAEAA5tYW51
|
||||||
|
MiwyLjUrMS4xMiwwLDMCGwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQ
|
||||||
|
AxI4TjpzlAsCwRAAtH3OO42yCd2B8Od4yS1yBDkaIFwEm8hF68eou6uaSDkKG8YZ
|
||||||
|
C3DUH7qk0nXEMQu/5J6RWZKlW1C8D3AkUR9A1g54o6mUg4IL5196XsrQRdVu64YF
|
||||||
|
nLCk17Piku1lMk+Re6bZ6uJv5UlSv8d0dvxmAYzjusyPyBC2VXy7B0CoDif6AmXt
|
||||||
|
aw2/V6m0dRrfFo4W9mJKUqTAJcdBOKzEiQb7qLnzuwy4CB5qsvnEQTqymoCXFXzg
|
||||||
|
VDCSKRLXnbDPbIs0TvsCmthn/w1hCgftPq4W0s7EUJBOhbrjF59+AuTb+U1wIXNR
|
||||||
|
1+DPF+V+5RlwWjOWMlsOVGk2jaxjVY8wuaD3rE6ISJkt1pRv/WVdY984rT7Eu94J
|
||||||
|
ZHnxPjFrb2ohFKjoBCt60kbgZbuQ6yvEma5lAF9K63gwMNNyGZvq6QWl58iouzuS
|
||||||
|
3B9t7EwGwFstJfaXVhn/rnIHoExgxVZMbbsmXiGJyE2KcfVmlZcEi0MIyqEeBSDD
|
||||||
|
gjpE4yVO6StBtJKfXra8rMwtsbWBw9MptPhcLvdWtN6TG0CxDyTHhdL1pSLNcwX1
|
||||||
|
CTVpwi6+WmGogcv0WFNn5caQUpu9le/v/5qLRK08KWOH8inMJmTfpJg/9869YJuF
|
||||||
|
vDKdzJd6jug5YQRfV/7YVC2hdSOBLvBuDpRINePrj9CKJ34qG+jRSJ5xwYk=
|
||||||
|
=IS3Y
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
30
CHANGELOG
30
CHANGELOG
@ -1,18 +1,14 @@
|
|||||||
3proxy-0.9.9 Released August, 20 2026
|
3proxy-0.9.9.1 Released October, 10 2026
|
||||||
|
|
||||||
! Fix: DNS replies are validated now: a reply from an address other than the nameserver the query was sent to, and a reply with a question section not matching the query, are dropped; both were accepted before
|
! Fix: crash (segmentation fault) on configuration reload (SIGUSR1) on a busy server: a closing session could still use its service after the reload had freed it; the race existed since 0.9.7, the 5 second linger added in 0.9.9 made it much more likely (#1278)
|
||||||
! Fix: socket leak with SOCKSv5 UDP ASSOCIATE through a parent proxy, sockets were accumulated in CLOSE_WAIT state until descriptors ran out
|
! Fix: -Di and -De (bind to interface) were not applied to SOCKSv5 UDP ASSOCIATE and BIND sockets, the FTP proxy data connection and connect back (#1277)
|
||||||
! Fix: file descriptor leak in HTTP proxy on the ftp:// request path
|
! Fix: SOCKSv5 UDP ASSOCIATE over IPv6: the source address of a datagram was truncated and the reply was sent to the wrong address (#1279)
|
||||||
! Fix: crash with illegal instruction on some platforms (e.g. some musl based Linux builds), caused by a memcpy on overlapping buffers
|
! Fix: SOCKSv5 UDP ASSOCIATE: an access rule with host names matched any datagram sent to a literal address; the address is used as the host name now, as it is for TCP requests
|
||||||
! Fix: extip and ha (HAProxy PROXY protocol) parents are applied to SOCKSv5 UDP ASSOCIATE now
|
! Fix: buffer could be insufficient for the headers the HTTP proxy adds after a pcre_rewrite had grown the request
|
||||||
! Fix: only socks5 and socks5+ parents are tried for UDP ASSOCIATE, other parent types can not be used for UDP
|
! Fix: heap buffer overflow in pcre_rewrite: a $N reference to a group which did not match was written out as its digits, which the space allocated for the result did not count
|
||||||
! Fix: udppm through a SOCKSv5 parent did not work
|
! Fix: pcre_extend did nothing, the rules it appended were never consulted
|
||||||
! Fix: -Ne and -Ni options were never applied, the option letter was not parsed; -Ne is not applied to the UDP ASSOCIATE reply anymore, -Ni is applied to it
|
! Fix: certificates generated for TLS MitM (openssl) carried no subject and authority key identifiers and were refused by strict verifiers, including macOS clients, OpenSSL with x509_strict and Python 3.13
|
||||||
! Fix: -4 / -6 handling for UDP in socks; a single UDP association can use both IPv4 and IPv6 destinations now
|
! Fix: null pointer dereference in ftppr on PASS without USER and in smtpp on a user name without a host
|
||||||
! Fix: a datagram with a null destination address is dropped now
|
! Fix: no service started with wolfSSL on glibc: the default thread stack was too small for wolfSSL thread-local storage, pthread_create() failed and the failure was not reported
|
||||||
! Fix: DNS over TCP: a reply which did not fit a single read was never processed
|
! Fix: dnspr did not work on Windows, the socket it answers from could not be bound
|
||||||
! Documentation: "How to apply ACLs to UDP traffic" added to HOWTO; authentication cache, ACL and UDP notes added to "Optimizing 3proxy for High Load" and to security recommendations
|
- Windows binaries are no longer signed with a self-signed Authenticode certificate, it gave no trust and triggered antivirus false positives
|
||||||
+ SOCKSv5 UDP: the destination of every datagram is authorized, so ACLs limiting the destination address, host name or port apply to UDP traffic now; the parent proxy and the external address are selected for the destination of the datagram and not for the UDP ASSOCIATE request
|
|
||||||
+ socks: -U option to control what happens when the destination changes within an UDP association: log it, authorize it, both (default) or neither
|
|
||||||
+ -C option (for TCP services) to terminate the session as soon as any of the sides closes the connection; by default the session is kept until both sides close it (TCP half-close)
|
|
||||||
+ timeouts: LINGER value added (11th, default 5), used to deliver buffered data after one of the sides has closed its sending side and as SO_LINGER value on outgoing connections
|
|
||||||
|
|||||||
@ -1,18 +1,14 @@
|
|||||||
3proxy-0.9.9 Вышел 20 Августа 2026
|
3proxy-0.9.9.1 Вышел 10 Октября 2026
|
||||||
|
|
||||||
! Исправление: ответы DNS теперь проверяются: ответ с адреса, отличного от адреса сервера имён, которому был отправлен запрос, а также ответ с секцией вопроса, не совпадающей с запросом, отбрасываются; ранее оба принимались
|
! Исправление: падение (segmentation fault) при перезагрузке конфигурации (SIGUSR1) на нагруженном сервере: закрывающаяся сессия могла обращаться к службе после того, как перезагрузка её освободила; гонка существовала с 0.9.7, а добавленная в 0.9.9 задержка закрытия (linger) в 5 секунд сделала её гораздо вероятнее (#1278)
|
||||||
! Исправление: утечка сокетов при SOCKSv5 UDP ASSOCIATE через вышестоящий прокси, сокеты накапливались в состоянии CLOSE_WAIT до исчерпания дескрипторов
|
! Исправление: -Di и -De (привязка к интерфейсу) не применялись к сокетам SOCKSv5 UDP ASSOCIATE и BIND, к соединению данных FTP прокси и к обратному соединению (connect back) (#1277)
|
||||||
! Исправление: утечка файловых дескрипторов в HTTP-прокси на пути обработки запроса ftp://
|
! Исправление: SOCKSv5 UDP ASSOCIATE по IPv6: адрес отправителя датаграммы обрезался, и ответ отправлялся не на тот адрес (#1279)
|
||||||
! Исправление: аварийное завершение с недопустимой инструкцией на некоторых платформах (например, в некоторых сборках Linux на основе musl) из-за memcpy на перекрывающихся буферах
|
! Исправление: SOCKSv5 UDP ASSOCIATE: правило доступа с именами хостов срабатывало для любой датаграммы, отправленной на адрес, а не на имя; теперь адрес используется как имя хоста, так же как для запросов TCP
|
||||||
! Исправление: родители типа extip и ha (HAProxy PROXY protocol) теперь применяются к SOCKSv5 UDP ASSOCIATE
|
! Исправление: буфера могло не хватить для заголовков, добавляемых HTTP прокси, после того как pcre_rewrite увеличил запрос
|
||||||
! Исправление: для UDP ASSOCIATE используются только родители socks5 и socks5+, остальные типы для UDP неприменимы
|
! Исправление: переполнение буфера в куче в pcre_rewrite: ссылка $N на группу, не участвовавшую в совпадении, выводилась своими цифрами, которые не учитывались при выделении памяти под результат
|
||||||
! Исправление: udppm через вышестоящий прокси SOCKSv5 не работал
|
! Исправление: pcre_extend ничего не делал, добавленные им правила никогда не проверялись
|
||||||
! Исправление: опции -Ne и -Ni никогда не применялись, буква опции не разбиралась; -Ne больше не применяется к ответу на UDP ASSOCIATE, -Ni применяется к нему
|
! Исправление: сертификаты, создаваемые для TLS MitM (openssl), не содержали идентификаторов ключа субъекта и издателя и отвергались строгой проверкой, в том числе клиентами macOS, OpenSSL с x509_strict и Python 3.13
|
||||||
! Исправление: обработка -4 / -6 для UDP в socks; одна UDP-ассоциация теперь может использовать адреса назначения и IPv4, и IPv6
|
! Исправление: обращение по нулевому указателю в ftppr при PASS без USER и в smtpp при имени пользователя без хоста
|
||||||
! Исправление: датаграмма с нулевым адресом назначения теперь отбрасывается
|
! Исправление: с wolfSSL на glibc не запускалась ни одна служба: стека потока по умолчанию не хватало для thread-local памяти wolfSSL, pthread_create() завершался ошибкой, о которой не сообщалось
|
||||||
! Исправление: DNS поверх TCP: ответ, не помещавшийся в одно чтение, никогда не обрабатывался
|
! Исправление: dnspr не работал в Windows, сокет, с которого он отвечает, не удавалось привязать
|
||||||
! Документация: в HOWTO добавлен раздел "Как применять ACL к UDP-трафику"; в "Optimizing 3proxy for High Load" и в рекомендации по безопасности добавлены заметки о кэше аутентификации, ACL и UDP
|
- Двоичные файлы для Windows больше не подписываются самоподписанным сертификатом Authenticode: доверия он не давал и вызывал ложные срабатывания антивирусов
|
||||||
+ SOCKSv5 UDP: адрес назначения каждой датаграммы авторизуется, поэтому ACL, ограничивающие адрес назначения, имя хоста или порт, теперь применяются к UDP-трафику; вышестоящий прокси и внешний адрес выбираются для адреса назначения датаграммы, а не для запроса UDP ASSOCIATE
|
|
||||||
+ socks: опция -U для управления тем, что происходит при смене адреса назначения в рамках UDP-ассоциации: журналировать, авторизовать, и то и другое (по умолчанию) или ничего
|
|
||||||
+ Опция -C (для TCP-сервисов) завершает сессию, как только любая из сторон закрывает соединение; по умолчанию сессия сохраняется, пока соединение не закроют обе стороны (полузакрытие TCP)
|
|
||||||
+ timeouts: добавлено значение LINGER (11-е, по умолчанию 5), используется для доставки буферизованных данных после того, как одна из сторон закрыла свою передающую сторону, а также как значение SO_LINGER для исходящих соединений
|
|
||||||
|
|||||||
@ -52,14 +52,14 @@ ifeq ($(LIBSTATIC), true)
|
|||||||
STATIC_SUFFIX = -Wl,-Bdynamic
|
STATIC_SUFFIX = -Wl,-Bdynamic
|
||||||
ZLIB = -lz -lzstd
|
ZLIB = -lz -lzstd
|
||||||
endif
|
endif
|
||||||
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
WOLFSSL_CHECK ?= $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
||||||
ifeq ($(WOLFSSL_CHECK), true)
|
ifeq ($(WOLFSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
|
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
|
||||||
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
||||||
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
||||||
ZLIB :=
|
ZLIB :=
|
||||||
else
|
else
|
||||||
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
OPENSSL_CHECK ?= $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
||||||
ifeq ($(OPENSSL_CHECK), true)
|
ifeq ($(OPENSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX)
|
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX)
|
||||||
CFLAGS += -DWITH_SSL
|
CFLAGS += -DWITH_SSL
|
||||||
@ -68,13 +68,13 @@ else
|
|||||||
ZLIB :=
|
ZLIB :=
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
PCRE_CHECK ?= $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
||||||
ifeq ($(PCRE_CHECK), true)
|
ifeq ($(PCRE_CHECK), true)
|
||||||
CFLAGS += -DWITH_PCRE
|
CFLAGS += -DWITH_PCRE
|
||||||
PCRE_OBJS = pcre$(OBJSUFFICS)
|
PCRE_OBJS = pcre$(OBJSUFFICS)
|
||||||
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
|
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
|
||||||
endif
|
endif
|
||||||
PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
|
PAM_CHECK ?= $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
|
||||||
ifeq ($(PAM_CHECK), true)
|
ifeq ($(PAM_CHECK), true)
|
||||||
PLUGINS += PamAuth
|
PLUGINS += PamAuth
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -60,14 +60,14 @@ ifeq ($(LIBSTATIC), true)
|
|||||||
ZLIB = -lz -lzstd
|
ZLIB = -lz -lzstd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
WOLFSSL_CHECK ?= $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
||||||
ifeq ($(WOLFSSL_CHECK), true)
|
ifeq ($(WOLFSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
|
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
|
||||||
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
||||||
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
||||||
ZLIB :=
|
ZLIB :=
|
||||||
else
|
else
|
||||||
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
OPENSSL_CHECK ?= $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
||||||
ifeq ($(OPENSSL_CHECK), true)
|
ifeq ($(OPENSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
|
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
|
||||||
CFLAGS += -DWITH_SSL
|
CFLAGS += -DWITH_SSL
|
||||||
@ -76,13 +76,13 @@ else
|
|||||||
ZLIB :=
|
ZLIB :=
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
PCRE_CHECK ?= $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
||||||
ifeq ($(PCRE_CHECK), true)
|
ifeq ($(PCRE_CHECK), true)
|
||||||
CFLAGS += -DWITH_PCRE
|
CFLAGS += -DWITH_PCRE
|
||||||
PCRE_OBJS = pcre$(OBJSUFFICS)
|
PCRE_OBJS = pcre$(OBJSUFFICS)
|
||||||
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
|
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
|
||||||
endif
|
endif
|
||||||
PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
|
PAM_CHECK ?= $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
|
||||||
ifeq ($(PAM_CHECK), true)
|
ifeq ($(PAM_CHECK), true)
|
||||||
PLUGINS += PamAuth
|
PLUGINS += PamAuth
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -31,20 +31,20 @@ COMPATLIBS =
|
|||||||
MAKEFILE = Makefile.Solaris
|
MAKEFILE = Makefile.Solaris
|
||||||
PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
|
PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
|
||||||
|
|
||||||
WOLFSSL_CHECK = $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testwssl testwssl.o -lwolfssl 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
WOLFSSL_CHECK = $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testwssl testwssl.o -lwolfssl 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
||||||
ifeq ($(WOLFSSL_CHECK), true)
|
ifeq ($(WOLFSSL_CHECK), true)
|
||||||
LIBS += -lwolfssl
|
LIBS += -lwolfssl
|
||||||
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
||||||
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
||||||
else
|
else
|
||||||
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
OPENSSL_CHECK = $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
||||||
ifeq ($(OPENSSL_CHECK), true)
|
ifeq ($(OPENSSL_CHECK), true)
|
||||||
LIBS += -l crypto -l ssl
|
LIBS += -l crypto -l ssl
|
||||||
CFLAGS += -DWITH_SSL
|
CFLAGS += -DWITH_SSL
|
||||||
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
PCRE_CHECK = $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
||||||
ifeq ($(PCRE_CHECK), true)
|
ifeq ($(PCRE_CHECK), true)
|
||||||
CFLAGS += -DWITH_PCRE
|
CFLAGS += -DWITH_PCRE
|
||||||
PCRE_OBJS = pcre$(OBJSUFFICS)
|
PCRE_OBJS = pcre$(OBJSUFFICS)
|
||||||
|
|||||||
@ -54,14 +54,14 @@ ifeq ($(LIBSTATIC), true)
|
|||||||
STATIC_SUFFIX = -Wl,-Bdynamic
|
STATIC_SUFFIX = -Wl,-Bdynamic
|
||||||
ZLIB = -lz -lzstd
|
ZLIB = -lz -lzstd
|
||||||
endif
|
endif
|
||||||
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
WOLFSSL_CHECK ?= $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
|
||||||
ifeq ($(WOLFSSL_CHECK), true)
|
ifeq ($(WOLFSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
|
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
|
||||||
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
||||||
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
||||||
ZLIB :=
|
ZLIB :=
|
||||||
else
|
else
|
||||||
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
OPENSSL_CHECK ?= $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
|
||||||
ifeq ($(OPENSSL_CHECK), true)
|
ifeq ($(OPENSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
|
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
|
||||||
CFLAGS += -DWITH_SSL
|
CFLAGS += -DWITH_SSL
|
||||||
@ -70,13 +70,13 @@ else
|
|||||||
ZLIB :=
|
ZLIB :=
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
PCRE_CHECK ?= $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
|
||||||
ifeq ($(PCRE_CHECK), true)
|
ifeq ($(PCRE_CHECK), true)
|
||||||
CFLAGS += -DWITH_PCRE
|
CFLAGS += -DWITH_PCRE
|
||||||
PCRE_OBJS = pcre$(OBJSUFFICS)
|
PCRE_OBJS = pcre$(OBJSUFFICS)
|
||||||
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
|
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
|
||||||
endif
|
endif
|
||||||
PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
|
PAM_CHECK ?= $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
|
||||||
ifeq ($(PAM_CHECK), true)
|
ifeq ($(PAM_CHECK), true)
|
||||||
PLUGINS += PamAuth
|
PLUGINS += PamAuth
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -47,14 +47,14 @@ ifeq ($(LIBSTATIC), true)
|
|||||||
STATIC_SUFFIX = -Wl,-Bdynamic
|
STATIC_SUFFIX = -Wl,-Bdynamic
|
||||||
ZLIB = -lz
|
ZLIB = -lz
|
||||||
endif
|
endif
|
||||||
WOLFSSL_CHECK = $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -o testwssl - 2>/dev/null && rm testwssl && echo true||echo false)
|
WOLFSSL_CHECK = $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -o testwssl - 2>/dev/null && rm testwssl && echo true||echo false)
|
||||||
ifeq ($(WOLFSSL_CHECK), true)
|
ifeq ($(WOLFSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -lws2_32
|
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -lws2_32
|
||||||
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
|
||||||
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
|
||||||
ZLIB :=
|
ZLIB :=
|
||||||
else
|
else
|
||||||
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -o testssl - 2>/dev/null && rm testssl && echo true||echo false)
|
OPENSSL_CHECK = $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -o testssl - 2>/dev/null && rm testssl && echo true||echo false)
|
||||||
ifeq ($(OPENSSL_CHECK), true)
|
ifeq ($(OPENSSL_CHECK), true)
|
||||||
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -lcrypt32
|
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -lcrypt32
|
||||||
CFLAGS += -DWITH_SSL
|
CFLAGS += -DWITH_SSL
|
||||||
@ -63,11 +63,11 @@ else
|
|||||||
ZLIB :=
|
ZLIB :=
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false)
|
PAM_CHECK = $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false)
|
||||||
ifeq ($(PAM_CHECK), true)
|
ifeq ($(PAM_CHECK), true)
|
||||||
PLUGINS += PamAuth
|
PLUGINS += PamAuth
|
||||||
endif
|
endif
|
||||||
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false)
|
PCRE_CHECK = $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false)
|
||||||
ifeq ($(PCRE_CHECK), true)
|
ifeq ($(PCRE_CHECK), true)
|
||||||
CFLAGS += -DWITH_PCRE
|
CFLAGS += -DWITH_PCRE
|
||||||
PCRE_OBJS = pcre$(OBJSUFFICS)
|
PCRE_OBJS = pcre$(OBJSUFFICS)
|
||||||
|
|||||||
59
README.md
59
README.md
@ -6,13 +6,52 @@
|
|||||||
|
|
||||||
### Branches
|
### Branches
|
||||||
|
|
||||||
- **Master** (stable) branch - 3proxy 0.9
|
- **Master** (stable) branch - 3proxy 1.0
|
||||||
- **Devel** branch - 3proxy 10 (don't use it)
|
- **0.9** (LTS) branch - 3proxy 0.9 maintenance branch, this branch
|
||||||
|
- **Devel** branch - 3proxy 2.0-devel (don't use it)
|
||||||
|
|
||||||
### Binaries (deb / rpm / Windows zip)
|
### Binaries (deb / rpm / Windows zip)
|
||||||
|
|
||||||
https://github.com/3proxy/3proxy/releases
|
https://github.com/3proxy/3proxy/releases
|
||||||
|
|
||||||
|
### Package repository (apt / dnf)
|
||||||
|
|
||||||
|
Signed apt and dnf repositories are published at https://3proxy.org/repo/ in
|
||||||
|
two channels: `lts` (0.9 branch) and `current` (master).
|
||||||
|
|
||||||
|
Debian 12 and Ubuntu 22.04 or newer:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo curl -fsSL https://3proxy.org/repo/3proxy-release-key.asc \
|
||||||
|
-o /usr/share/keyrings/3proxy.asc
|
||||||
|
sudo tee /etc/apt/sources.list.d/3proxy.sources <<EOF
|
||||||
|
Types: deb
|
||||||
|
URIs: https://3proxy.org/repo/deb
|
||||||
|
Suites: lts
|
||||||
|
Components: main
|
||||||
|
Signed-By: /usr/share/keyrings/3proxy.asc
|
||||||
|
EOF
|
||||||
|
sudo apt update && sudo apt install 3proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
AlmaLinux, RHEL, Rocky and CentOS Stream 8, 9 and 10:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tee /etc/yum.repos.d/3proxy.repo <<EOF
|
||||||
|
[3proxy]
|
||||||
|
name=3proxy
|
||||||
|
baseurl=https://3proxy.org/repo/rpm/lts/el\$releasever/\$basearch/
|
||||||
|
enabled=1
|
||||||
|
gpgcheck=1
|
||||||
|
repo_gpgcheck=1
|
||||||
|
gpgkey=https://3proxy.org/repo/3proxy-release-key.asc
|
||||||
|
EOF
|
||||||
|
sudo dnf install 3proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
Both the packages and the repository metadata are signed. See
|
||||||
|
https://3proxy.org/repo/ for the `current` channel and for release key details.
|
||||||
|
|
||||||
### Docker images
|
### Docker images
|
||||||
|
|
||||||
https://hub.docker.com/r/3proxy/3proxy
|
https://hub.docker.com/r/3proxy/3proxy
|
||||||
@ -29,9 +68,9 @@ Documentation (man pages and HTML) available with download, on https://3proxy.or
|
|||||||
|
|
||||||
## Docker images
|
## Docker images
|
||||||
|
|
||||||
3 docker configurations are provided, default (full) also tagged as `:latest`, `:busybox` and `:minimal`, all refer to newest stable version. Except busybox, images are distroless and contain only binaries, you can not sh inside the container. `:busybox` contains busybox shell.
|
3 docker configurations are provided, default (full) also tagged as `:lts`, `:lts-busybox` and `:lts-minimal`, all refer to newest 0.9 LTS version. Images built from this branch use the `lts` tags, images built from the master branch use `:latest`, `:busybox` and `:minimal`. Use the `lts` tags to stay on the 0.9 branch, use a version tag (e.g. `:0.9.9`) to pin an exact version. Except busybox, images are distroless and contain only binaries, you can not sh inside the container. `:lts-busybox` contains busybox shell.
|
||||||
|
|
||||||
### Default image (`:latest`):
|
### Default image (`:lts`):
|
||||||
|
|
||||||
Full installation requires to mount /etc/3proxy/3proxy.cfg files.
|
Full installation requires to mount /etc/3proxy/3proxy.cfg files.
|
||||||
|
|
||||||
@ -42,7 +81,7 @@ echo "log
|
|||||||
nserver 8.8.8.8
|
nserver 8.8.8.8
|
||||||
nscache 65536
|
nscache 65536
|
||||||
proxy -p3129" | docker config create 3proxy
|
proxy -p3129" | docker config create 3proxy
|
||||||
docker run --read-only -p 3129:3129 --config source=3proxy,target=/etc/3proxy/3proxy.cfg --name 3proxy.full docker.io/3proxy/3proxy
|
docker run --read-only -p 3129:3129 --config source=3proxy,target=/etc/3proxy/3proxy.cfg --name 3proxy.full docker.io/3proxy/3proxy:lts
|
||||||
```
|
```
|
||||||
|
|
||||||
`podman` does not support `config` as above.
|
`podman` does not support `config` as above.
|
||||||
@ -60,13 +99,13 @@ podman run --read-only -p 3129:3129 -v /path/to/local/config/directory/3proxy.cf
|
|||||||
use `log` without pathname in config to log to stdout.
|
use `log` without pathname in config to log to stdout.
|
||||||
plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) and since 0.9.6 symlinked by /lib and /lib64 in both chroot and non-chroot configurations, so no full path is required in `plugin` command. Use e.g. `plugin SSLPlugin.ls.so ssl_plugin`. SSLPlugin is supported since 0.9.6. Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. -`-network host` mode or `-P` for `docker run`.
|
plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) and since 0.9.6 symlinked by /lib and /lib64 in both chroot and non-chroot configurations, so no full path is required in `plugin` command. Use e.g. `plugin SSLPlugin.ls.so ssl_plugin`. SSLPlugin is supported since 0.9.6. Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. -`-network host` mode or `-P` for `docker run`.
|
||||||
|
|
||||||
since 0.9.6 images are distroless (except :busybox) it's recommended to use with read only file system, there are no benefits from chroot. For compatibility, you still can use chroot installation by mounting directory with 3proxy.cfg to /usr/local/3proxy/config.
|
since 0.9.6 images are distroless (except :lts-busybox) it's recommended to use with read only file system, there are no benefits from chroot. For compatibility, you still can use chroot installation by mounting directory with 3proxy.cfg to /usr/local/3proxy/config.
|
||||||
|
|
||||||
### Busybox image (`:busybox`):
|
### Busybox image (`:lts-busybox`):
|
||||||
|
|
||||||
`full` with busybox added, to allow `sh` and few more commands like `sed` inside container. All libraries are in /lib, so chroot configuration can not use plugins.
|
`full` with busybox added, to allow `sh` and few more commands like `sed` inside container. All libraries are in /lib, so chroot configuration can not use plugins.
|
||||||
|
|
||||||
### Interactive `:minimal` image:
|
### Interactive `:lts-minimal` image:
|
||||||
|
|
||||||
Dockerfile for "interactive" minimal 3proxy execution, no configuration mounting is required, configuration
|
Dockerfile for "interactive" minimal 3proxy execution, no configuration mounting is required, configuration
|
||||||
is accepted from stdin. Use `end` command to indicate the end of configuration. Use `log` for stdout logging.
|
is accepted from stdin. Use `end` command to indicate the end of configuration. Use `log` for stdout logging.
|
||||||
@ -76,7 +115,7 @@ since 0.9.6 images are distroless (except :busybox) it's recommended to use with
|
|||||||
|
|
||||||
Run example:
|
Run example:
|
||||||
|
|
||||||
`docker run --read-only -i -p 3129:3129 --name 3proxy docker.io/3proxy/3proxy:minimal`
|
`docker run --read-only -i -p 3129:3129 --name 3proxy docker.io/3proxy/3proxy:lts-minimal`
|
||||||
or
|
or
|
||||||
`docker start -ai 3proxy` to start existing container
|
`docker start -ai 3proxy` to start existing container
|
||||||
|
|
||||||
@ -92,7 +131,7 @@ end
|
|||||||
|
|
||||||
Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. `--network host` mode or `-P` to `docker run`.
|
Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. `--network host` mode or `-P` to `docker run`.
|
||||||
|
|
||||||
`:minimal` without version specified uses current stable version.
|
`:lts-minimal` without version specified uses current 0.9 LTS version.
|
||||||
|
|
||||||
## Building and installation
|
## Building and installation
|
||||||
|
|
||||||
|
|||||||
60
SECURITY.md
60
SECURITY.md
@ -12,3 +12,63 @@
|
|||||||
Report to 3proxy@3proxy.org or via [GitHub security reporting](https://github.com/3proxy/3proxy/security)
|
Report to 3proxy@3proxy.org or via [GitHub security reporting](https://github.com/3proxy/3proxy/security)
|
||||||
|
|
||||||
For High/Critical patched version is released within 2 weeks
|
For High/Critical patched version is released within 2 weeks
|
||||||
|
|
||||||
|
## Verifying downloads
|
||||||
|
|
||||||
|
Release binaries and the source tarball are published with SHA256 checksums, an
|
||||||
|
OpenPGP signature and a GitHub build provenance attestation.
|
||||||
|
|
||||||
|
The release signing key is `3proxy-release-key.asc` in the root of this
|
||||||
|
repository, an RSA-4096 key:
|
||||||
|
|
||||||
|
```
|
||||||
|
pub rsa4096 2026-08-21 [SC]
|
||||||
|
FC12 2144 99FC C7BA 1CFF 6CDC 0312 384E 3A73 940B
|
||||||
|
uid 3proxy release signing <3proxy@3proxy.org>
|
||||||
|
```
|
||||||
|
|
||||||
|
Import it once:
|
||||||
|
|
||||||
|
```
|
||||||
|
gpg --import 3proxy-release-key.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
Checksums and the checksum file signature:
|
||||||
|
|
||||||
|
```
|
||||||
|
gpg --verify SHA256SUMS-x86_64.asc SHA256SUMS-x86_64
|
||||||
|
sha256sum -c SHA256SUMS-x86_64
|
||||||
|
```
|
||||||
|
|
||||||
|
The source tarball published with each release is signed as well:
|
||||||
|
|
||||||
|
```
|
||||||
|
gpg --verify SHA256SUMS-src.asc SHA256SUMS-src
|
||||||
|
sha256sum -c SHA256SUMS-src
|
||||||
|
gpg --verify 3proxy-0.9.9.tar.gz.asc 3proxy-0.9.9.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
Prefer it over the `Source code (tar.gz)` link GitHub generates automatically:
|
||||||
|
only the published tarball is signed. It is produced with `git archive` from
|
||||||
|
the release tag, so it can be regenerated and compared byte for byte.
|
||||||
|
|
||||||
|
RPM packages are signed, the signature is checked by rpm itself:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo rpm --import 3proxy-release-key.asc
|
||||||
|
rpm -K 3proxy-0.9.9.x86_64.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
DEB packages are published with a detached signature:
|
||||||
|
|
||||||
|
```
|
||||||
|
gpg --verify 3proxy-0.9.9.x86_64.deb.asc 3proxy-0.9.9.x86_64.deb
|
||||||
|
```
|
||||||
|
|
||||||
|
Build provenance (which workflow, commit and runner produced the file) is
|
||||||
|
verified with the GitHub CLI:
|
||||||
|
|
||||||
|
```
|
||||||
|
gh attestation verify 3proxy-0.9.9.x86_64.rpm --owner 3proxy
|
||||||
|
gh attestation verify oci://docker.io/3proxy/3proxy:lts --owner 3proxy
|
||||||
|
```
|
||||||
|
|||||||
12
debian/changelog
vendored
12
debian/changelog
vendored
@ -1,3 +1,15 @@
|
|||||||
|
3proxy (0.9.9.1-1) buster; urgency=medium
|
||||||
|
|
||||||
|
*3proxy 0.9.9.1 initial build
|
||||||
|
|
||||||
|
-- z3APA3A <3apa3a@3proxy.org> Sat, 10 Oct 2026 16:57:17 +0000
|
||||||
|
|
||||||
|
3proxy (0.9.9.0-1) buster; urgency=medium
|
||||||
|
|
||||||
|
*3proxy 0.9.9.0 initial build
|
||||||
|
|
||||||
|
-- z3APA3A <3apa3a@3proxy.org> Thu, 20 Aug 2026 19:12:35 +0300
|
||||||
|
|
||||||
3proxy (0.9.9-1) buster; urgency=medium
|
3proxy (0.9.9-1) buster; urgency=medium
|
||||||
|
|
||||||
*3proxy 0.9.9 initial build
|
*3proxy 0.9.9 initial build
|
||||||
|
|||||||
12
doc/changelog/0/9/9/1
Normal file
12
doc/changelog/0/9/9/1
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
! Fix: crash (segmentation fault) on configuration reload (SIGUSR1) on a busy server: a closing session could still use its service after the reload had freed it; the race existed since 0.9.7, the 5 second linger added in 0.9.9 made it much more likely (#1278)
|
||||||
|
! Fix: -Di and -De (bind to interface) were not applied to SOCKSv5 UDP ASSOCIATE and BIND sockets, the FTP proxy data connection and connect back (#1277)
|
||||||
|
! Fix: SOCKSv5 UDP ASSOCIATE over IPv6: the source address of a datagram was truncated and the reply was sent to the wrong address (#1279)
|
||||||
|
! Fix: SOCKSv5 UDP ASSOCIATE: an access rule with host names matched any datagram sent to a literal address; the address is used as the host name now, as it is for TCP requests
|
||||||
|
! Fix: buffer could be insufficient for the headers the HTTP proxy adds after a pcre_rewrite had grown the request
|
||||||
|
! Fix: heap buffer overflow in pcre_rewrite: a $N reference to a group which did not match was written out as its digits, which the space allocated for the result did not count
|
||||||
|
! Fix: pcre_extend did nothing, the rules it appended were never consulted
|
||||||
|
! Fix: certificates generated for TLS MitM (openssl) carried no subject and authority key identifiers and were refused by strict verifiers, including macOS clients, OpenSSL with x509_strict and Python 3.13
|
||||||
|
! Fix: null pointer dereference in ftppr on PASS without USER and in smtpp on a user name without a host
|
||||||
|
! Fix: no service started with wolfSSL on glibc: the default thread stack was too small for wolfSSL thread-local storage, pthread_create() failed and the failure was not reported
|
||||||
|
! Fix: dnspr did not work on Windows, the socket it answers from could not be bound
|
||||||
|
- Windows binaries are no longer signed with a self-signed Authenticode certificate, it gave no trust and triggered antivirus false positives
|
||||||
@ -1471,10 +1471,12 @@ allowed traffic in megabytes (MB). nocountin allows you to set exclusions.
|
|||||||
For name resolution and caching, use the commands nserver, nscache / nscache6, and nsrecord.
|
For name resolution and caching, use the commands nserver, nscache / nscache6, and nsrecord.
|
||||||
<pre>
|
<pre>
|
||||||
nserver 192.168.1.2
|
nserver 192.168.1.2
|
||||||
nserver 192.168.1.3:5353/tcp</pre>
|
nserver 192.168.1.3:5353/tcp
|
||||||
|
nserver [2001:4860:4860::8844]</pre>
|
||||||
sets DNS resolvers. 192.168.1.3 will be used via TCP/5353 (instead of default UDP/53)
|
sets DNS resolvers. 192.168.1.3 will be used via TCP/5353 (instead of default UDP/53)
|
||||||
only if 192.168.1.2 fails. Up to 5 nservers may be specified.
|
only if 192.168.1.2 fails. Up to 5 nservers may be specified.
|
||||||
If no nserver is configured, default system name resolution functions are used.
|
If no nserver is configured, default system name resolution functions are used.
|
||||||
|
An IPv6 address has to be written in square brackets.
|
||||||
<pre>
|
<pre>
|
||||||
nscache 65535
|
nscache 65535
|
||||||
nscache6 65535</pre>
|
nscache6 65535</pre>
|
||||||
|
|||||||
@ -1536,11 +1536,13 @@ socks -p1080
|
|||||||
nscache и nsrecord.
|
nscache и nsrecord.
|
||||||
<pre>
|
<pre>
|
||||||
nserver 192.168.1.2
|
nserver 192.168.1.2
|
||||||
nserver 192.168.1.3:5353/tcp</pre>
|
nserver 192.168.1.3:5353/tcp
|
||||||
|
nserver [2001:4860:4860::8844]</pre>
|
||||||
указывает 3proxy какие машины следует использвоать в качестве серверов
|
указывает 3proxy какие машины следует использвоать в качестве серверов
|
||||||
DNS. Сервер 192.168.1.3 будет использоваться по порту TCP/5353 (вместо дефолтного UDP/53) только при недостижимости
|
DNS. Сервер 192.168.1.3 будет использоваться по порту TCP/5353 (вместо дефолтного UDP/53) только при недостижимости
|
||||||
192.168.1.2. Можно указать до 5 серверов. Если nserver не указан, будут
|
192.168.1.2. Можно указать до 5 серверов. Если nserver не указан, будут
|
||||||
использованы системные функции разрешения имен.
|
использованы системные функции разрешения имен.
|
||||||
|
Адрес IPv6 необходимо записывать в квадратных скобках.
|
||||||
<pre>
|
<pre>
|
||||||
nscache 65535
|
nscache 65535
|
||||||
nscache6 65535</pre>
|
nscache6 65535</pre>
|
||||||
|
|||||||
@ -489,7 +489,11 @@ experimental.</p>
|
|||||||
Nameserver to use for name resolutions. If none specified
|
Nameserver to use for name resolutions. If none specified
|
||||||
system routines for name resolution is used. Optional port
|
system routines for name resolution is used. Optional port
|
||||||
number may be specified. If optional /tcp is added to IP
|
number may be specified. If optional /tcp is added to IP
|
||||||
address, name resolution is performed over TCP.</p>
|
address, name resolution is performed over TCP. An IPv6 address
|
||||||
|
has to be enclosed in square brackets: <br>
|
||||||
|
<b>nserver 1.1.1.1</b> <br>
|
||||||
|
<b>nserver [2001:4860:4860::8844]</b> <br>
|
||||||
|
<b>nserver [2001:4860:4860::8844]:5353/tcp</b></p>
|
||||||
|
|
||||||
|
|
||||||
<p style="margin-left:6%; margin-top: 1em"><b>authnserver</b>
|
<p style="margin-left:6%; margin-top: 1em"><b>authnserver</b>
|
||||||
|
|||||||
@ -514,6 +514,13 @@ system routines for name resolution is
|
|||||||
used. Optional port number may be specified.
|
used. Optional port number may be specified.
|
||||||
If optional /tcp is added to IP address, name resolution is
|
If optional /tcp is added to IP address, name resolution is
|
||||||
performed over TCP.
|
performed over TCP.
|
||||||
|
An IPv6 address has to be enclosed in square brackets:
|
||||||
|
.br
|
||||||
|
\fBnserver 1.1.1.1\fR
|
||||||
|
.br
|
||||||
|
\fBnserver [2001:4860:4860::8844]\fR
|
||||||
|
.br
|
||||||
|
\fBnserver [2001:4860:4860::8844]:5353/tcp\fR
|
||||||
|
|
||||||
.br
|
.br
|
||||||
.BR authnserver
|
.BR authnserver
|
||||||
|
|||||||
66
scripts/openwrt/Makefile
Normal file
66
scripts/openwrt/Makefile
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#
|
||||||
|
# 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))
|
||||||
59
scripts/openwrt/files/3proxy.config
Normal file
59
scripts/openwrt/files/3proxy.config
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
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'
|
||||||
460
scripts/openwrt/files/3proxy.init
Normal file
460
scripts/openwrt/files/3proxy.init
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
#!/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
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
Name: 3proxy
|
Name: 3proxy
|
||||||
Version: 0.9.9
|
Version: 0.9.9.1
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: 3proxy tiny proxy server
|
Summary: 3proxy tiny proxy server
|
||||||
License: GPL/LGPL/Apache/BSD
|
License: GPL/LGPL/Apache/BSD
|
||||||
@ -9,6 +9,9 @@ Prefix: %{_prefix}
|
|||||||
Packager: z3APA3A
|
Packager: z3APA3A
|
||||||
Source: https://github.com/%{packager}/%{name}/archive/%{version}.tar.gz
|
Source: https://github.com/%{packager}/%{name}/archive/%{version}.tar.gz
|
||||||
|
|
||||||
|
%global debug_package %{nil}
|
||||||
|
%global __requires_exclude ^/(usr/)?bin/3proxy$
|
||||||
|
|
||||||
%description
|
%description
|
||||||
3proxy is lightweight yet powerful proxy server
|
3proxy is lightweight yet powerful proxy server
|
||||||
|
|
||||||
|
|||||||
65
src/common.c
65
src/common.c
@ -182,7 +182,7 @@ int timeouts[12] = {
|
|||||||
EINVAL below it and the thread silently gets the 8M system default stack.
|
EINVAL below it and the thread silently gets the 8M system default stack.
|
||||||
*/
|
*/
|
||||||
size_t threadstacksize(int extra){
|
size_t threadstacksize(int extra){
|
||||||
long size = BASESTACKSIZE + extra;
|
long size = BASESTACKSIZE + TLSSTACKSIZE + extra;
|
||||||
|
|
||||||
if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN;
|
if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN;
|
||||||
return (size_t)size;
|
return (size_t)size;
|
||||||
@ -677,6 +677,49 @@ int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -Di / -De: ties a socket to the interface asked for, for TCP and UDP alike.
|
||||||
|
Where the option is set per protocol, family is the one of the address the
|
||||||
|
socket will be bound to. */
|
||||||
|
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family){
|
||||||
|
if(!device) return 0;
|
||||||
|
#if defined SO_BINDTODEVICE
|
||||||
|
if(sf->_setsockopt(state, sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1))
|
||||||
|
return 1;
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
idx = if_nametoindex(device);
|
||||||
|
if(!idx || (family == AF_INET && sf->_setsockopt(state, sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
||||||
|
return 1;
|
||||||
|
#ifndef NOIPV6
|
||||||
|
#ifndef IPV6_BOUND_IF
|
||||||
|
#define IPV6_BOUND_IF 125
|
||||||
|
#endif
|
||||||
|
if(family == AF_INET6 && sf->_setsockopt(state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the external side, a socket to be bound to sinsl */
|
||||||
|
int extbindtodevice(struct clientparam *param, SOCKET sock){
|
||||||
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
|
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->obindtodevice, *SAFAMILY(¶m->sinsl));
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the internal side, a socket to be bound to sincl */
|
||||||
|
int intbindtodevice(struct clientparam *param, SOCKET sock){
|
||||||
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
|
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->ibindtodevice, *SAFAMILY(¶m->sincl));
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int doconnect(struct clientparam * param){
|
int doconnect(struct clientparam * param){
|
||||||
SASIZETYPE size;
|
SASIZETYPE size;
|
||||||
|
|
||||||
@ -724,25 +767,7 @@ int doconnect(struct clientparam * param){
|
|||||||
setopts(param->remsock, param->srv->srvsockopts);
|
setopts(param->remsock, param->srv->srvsockopts);
|
||||||
|
|
||||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||||
#if defined SO_BINDTODEVICE
|
if(extbindtodevice(param, param->remsock)) return 12;
|
||||||
if(param->srv->obindtodevice) {
|
|
||||||
if(param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_BINDTODEVICE, param->srv->obindtodevice, strlen(param->srv->obindtodevice) + 1))
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
#elif defined IP_BOUND_IF
|
|
||||||
if(param->srv->obindtodevice) {
|
|
||||||
int idx;
|
|
||||||
idx = if_nametoindex(param->srv->obindtodevice);
|
|
||||||
if(!idx || (*SAFAMILY(¶m->sinsl) == AF_INET && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
|
||||||
return 12;
|
|
||||||
#ifndef NOIPV6
|
|
||||||
#ifndef IPV6_BOUND_IF
|
|
||||||
#define IPV6_BOUND_IF 125
|
|
||||||
#endif
|
|
||||||
if(*SAFAMILY(¶m->sinsl) == AF_INET6 && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 12;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -158,7 +158,12 @@ int start_proxy_thread(struct child * chp){
|
|||||||
pthread_attr_init(&pa);
|
pthread_attr_init(&pa);
|
||||||
pthread_attr_setstacksize(&pa,threadstacksize(conf.stacksize));
|
pthread_attr_setstacksize(&pa,threadstacksize(conf.stacksize));
|
||||||
pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
|
pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
|
||||||
pthread_create(&thread, &pa, startsrv, (void *)chp);
|
if(pthread_create(&thread, &pa, startsrv, (void *)chp)){
|
||||||
|
pthread_attr_destroy(&pa);
|
||||||
|
fprintf(stderr, "Failed to create service thread on line %d, try to set larger stacksize\n", linenum);
|
||||||
|
_3proxy_sem_unlock(conf.threadinit);
|
||||||
|
return(40);
|
||||||
|
}
|
||||||
pthread_attr_destroy(&pa);
|
pthread_attr_destroy(&pa);
|
||||||
#endif
|
#endif
|
||||||
_3proxy_sem_lock(conf.threadinit);
|
_3proxy_sem_lock(conf.threadinit);
|
||||||
|
|||||||
@ -64,6 +64,13 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
else if (!strncasecmp((char *)buf, "PASS ", 5)){
|
else if (!strncasecmp((char *)buf, "PASS ", 5)){
|
||||||
|
/* The user name carries the server to log in to, and it arrives
|
||||||
|
with USER. Without it there is nothing to log in to, and what
|
||||||
|
follows would read the name and the host as if there were. */
|
||||||
|
if(!param->hostname || !param->extusername){
|
||||||
|
socksend(param, param->ctrlsock, (unsigned char *)"503 Login with USER first\r\n", 27, conf.timeouts[STRING_S]);
|
||||||
|
RETURN(805);
|
||||||
|
}
|
||||||
param->extpassword = (unsigned char *)strdup((char *)buf+5);
|
param->extpassword = (unsigned char *)strdup((char *)buf+5);
|
||||||
inbuf = BUFSIZE;
|
inbuf = BUFSIZE;
|
||||||
res = ftplogin(param, (char *)buf, &inbuf);
|
res = ftplogin(param, (char *)buf, &inbuf);
|
||||||
@ -120,6 +127,7 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
clidatasock = INVALID_SOCKET;
|
clidatasock = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||||
|
if(intbindtodevice(param, clidatasock)){RETURN(822);}
|
||||||
*SAPORT(¶m->sincl) = 0;
|
*SAPORT(¶m->sincl) = 0;
|
||||||
if(param->srv->so._bind(param->sostate, clidatasock, (struct sockaddr *)¶m->sincl, SASIZE(¶m->sincl))){RETURN(822);}
|
if(param->srv->so._bind(param->sostate, clidatasock, (struct sockaddr *)¶m->sincl, SASIZE(¶m->sincl))){RETURN(822);}
|
||||||
if (pasv) {
|
if (pasv) {
|
||||||
|
|||||||
22
src/pcre.c
22
src/pcre.c
@ -265,6 +265,9 @@ static FILTER_ACTION pcre_filter_client(void *fo, struct clientparam * param, vo
|
|||||||
return (res)? CONTINUE:PASS;
|
return (res)? CONTINUE:PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* What a rewritten buffer keeps free for its caller to append to. */
|
||||||
|
#define PCRE_HEADROOM 1024
|
||||||
|
|
||||||
static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
|
||||||
PCRE2_SIZE *ovector;
|
PCRE2_SIZE *ovector;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@ -277,7 +280,7 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
#define pcrefd ((struct pcre_filter_data *)fc)
|
#define pcrefd ((struct pcre_filter_data *)fc)
|
||||||
|
|
||||||
for(acl = pcrefd->acl; acl; acl=acl->next){
|
for(acl = pcrefd->acl; acl; acl=acl->next){
|
||||||
if(pl->ACLMatches(pcrefd->acl, param)){
|
if(pl->ACLMatches(acl, param)){
|
||||||
match = 1;
|
match = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -324,12 +327,17 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
else if(*replace == '$' && isnumber(*(replace+1))){
|
else if(*replace == '$' && isnumber(*(replace+1))){
|
||||||
replace ++;
|
replace ++;
|
||||||
num = atoi(replace);
|
num = atoi(replace);
|
||||||
|
/* Past the digits first, and only then decide whether
|
||||||
|
the group is one to copy: the pass which measured
|
||||||
|
this string did it in that order, and a reference it
|
||||||
|
counted as nothing must not be written out as its
|
||||||
|
own digits here. */
|
||||||
|
while(isnumber(*replace)) replace++;
|
||||||
if(num > (count - 1)) continue;
|
if(num > (count - 1)) continue;
|
||||||
if(ovector[(num<<1)] == PCRE2_UNSET) continue;
|
if(ovector[(num<<1)] == PCRE2_UNSET) continue;
|
||||||
if(ovector[(num<<1) + 1] > (PCRE2_SIZE)*length_p || ovector[(num<<1)] > ovector[(num<<1) + 1]) continue;
|
if(ovector[(num<<1) + 1] > (PCRE2_SIZE)*length_p || ovector[(num<<1)] > ovector[(num<<1) + 1]) continue;
|
||||||
memcpy(target, *buf_p + ovector[(num<<1)], ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
memcpy(target, *buf_p + ovector[(num<<1)], ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
||||||
target += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
target += (ovector[(num<<1) + 1] - ovector[(num<<1)]);
|
||||||
while(isnumber(*replace)) replace++;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*target++ = *replace++;
|
*target++ = *replace++;
|
||||||
@ -338,7 +346,13 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
repsz = (int)(target - tmpbuf);
|
repsz = (int)(target - tmpbuf);
|
||||||
memcpy(target, *buf_p + ovector[1], *length_p - ovector[1]);
|
memcpy(target, *buf_p + ovector[1], *length_p - ovector[1]);
|
||||||
if((ovector[0] + replen + 1) > *bufsize_p){
|
if((ovector[0] + replen + 1) > *bufsize_p){
|
||||||
newbuf = pl->mallocfunc(ovector[0] + replen + 1);
|
/* Room beyond what was produced: whoever asked for the
|
||||||
|
filtering usually has something of its own to add, and a
|
||||||
|
buffer sized to the last byte written leaves nowhere to
|
||||||
|
put it. The size reported is the size allocated. */
|
||||||
|
int newsize = ovector[0] + replen + 1 + PCRE_HEADROOM;
|
||||||
|
|
||||||
|
newbuf = pl->mallocfunc(newsize);
|
||||||
if(!newbuf){
|
if(!newbuf){
|
||||||
pl->freefunc(tmpbuf);
|
pl->freefunc(tmpbuf);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
@ -346,7 +360,7 @@ static FILTER_ACTION pcre_filter_buffer(void *fc, struct clientparam *param, uns
|
|||||||
memcpy(newbuf, *buf_p, ovector[0]);
|
memcpy(newbuf, *buf_p, ovector[0]);
|
||||||
pl->freefunc(*buf_p);
|
pl->freefunc(*buf_p);
|
||||||
*buf_p = (unsigned char *)newbuf;
|
*buf_p = (unsigned char *)newbuf;
|
||||||
*bufsize_p = ovector[0] + replen + 1;
|
*bufsize_p = newsize;
|
||||||
}
|
}
|
||||||
memcpy(*buf_p + ovector[0], tmpbuf, replen);
|
memcpy(*buf_p + ovector[0], tmpbuf, replen);
|
||||||
pl->freefunc(tmpbuf);
|
pl->freefunc(tmpbuf);
|
||||||
|
|||||||
27
src/proxy.c
27
src/proxy.c
@ -132,6 +132,12 @@ char * proxy_stringtable[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define LINESIZE 32768
|
#define LINESIZE 32768
|
||||||
|
/* "Content-Length: " plus 20 digits plus CRLF and a NUL, rounded up */
|
||||||
|
#define CLHDRSIZE 48
|
||||||
|
/* what the headers this proxy adds of its own can come to: a Forwarded or
|
||||||
|
Via with a host name in it, a Connection, a Proxy-support and a
|
||||||
|
Proxy-Authorization carrying an encoded user and password */
|
||||||
|
#define HDRRESERVE 2048
|
||||||
#define BUFSIZE (LINESIZE*2)
|
#define BUFSIZE (LINESIZE*2)
|
||||||
#define FTPBUFSIZE 1536
|
#define FTPBUFSIZE 1536
|
||||||
|
|
||||||
@ -151,6 +157,20 @@ static int send_st(struct clientparam *param, int idx){
|
|||||||
return socksend(param, param->clisock, (unsigned char *)proxy_stringtable[idx], pst_len(idx), conf.timeouts[STRING_S]);
|
return socksend(param, param->clisock, (unsigned char *)proxy_stringtable[idx], pst_len(idx), conf.timeouts[STRING_S]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Makes room in a buffer whose size is tracked. A filter may hand back one
|
||||||
|
holding exactly what it produced, so nothing may be added to it without
|
||||||
|
asking for the room first. Returns 1 when the room cannot be had. */
|
||||||
|
static int growbuf(unsigned char **buf, int *bufsize, int need){
|
||||||
|
unsigned char *newbuf;
|
||||||
|
|
||||||
|
if(need <= *bufsize) return 0;
|
||||||
|
need += BUFSIZE; /* for what follows too, not just this */
|
||||||
|
if(!(newbuf = realloc(*buf, need))) return 1;
|
||||||
|
*buf = newbuf;
|
||||||
|
*bufsize = need;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void freeptr(void *p){
|
static void freeptr(void *p){
|
||||||
void **pp = (void **)p;
|
void **pp = (void **)p;
|
||||||
if(*pp) { free(*pp); *pp = NULL; }
|
if(*pp) { free(*pp); *pp = NULL; }
|
||||||
@ -587,6 +607,10 @@ for(;;){
|
|||||||
RETURN(0);
|
RETURN(0);
|
||||||
}
|
}
|
||||||
if(action != PASS) RETURN(517);
|
if(action != PASS) RETURN(517);
|
||||||
|
/* A filter may have returned a buffer sized to exactly what it produced.
|
||||||
|
The headers this proxy adds of its own go in after it, so the room for
|
||||||
|
them is taken back before anything is written. */
|
||||||
|
if(growbuf(&buf, &bufsize, inbuf + HDRRESERVE)) RETURN(21);
|
||||||
param->nolongdatfilter = 0;
|
param->nolongdatfilter = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -620,6 +644,7 @@ for(;;){
|
|||||||
contentlength64 = param->cliinbuf;
|
contentlength64 = param->cliinbuf;
|
||||||
param->nolongdatfilter = 1;
|
param->nolongdatfilter = 1;
|
||||||
}
|
}
|
||||||
|
if(growbuf(&buf, &bufsize, (int)strlen((char *)buf) + CLHDRSIZE)) RETURN(21);
|
||||||
sprintf((char*)buf+strlen((char *)buf), "Content-Length: %"PRIu64"\r\n", contentlength64);
|
sprintf((char*)buf+strlen((char *)buf), "Content-Length: %"PRIu64"\r\n", contentlength64);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1097,6 +1122,7 @@ for(;;){
|
|||||||
RETURN(0);
|
RETURN(0);
|
||||||
}
|
}
|
||||||
if(action != PASS) RETURN(517);
|
if(action != PASS) RETURN(517);
|
||||||
|
if(growbuf(&buf, &bufsize, inbuf + HDRRESERVE)) RETURN(21);
|
||||||
|
|
||||||
param->nolongdatfilter = 0;
|
param->nolongdatfilter = 0;
|
||||||
|
|
||||||
@ -1120,6 +1146,7 @@ for(;;){
|
|||||||
}
|
}
|
||||||
if(action != PASS) RETURN(517);
|
if(action != PASS) RETURN(517);
|
||||||
contentlength64 = param->srvinbuf;
|
contentlength64 = param->srvinbuf;
|
||||||
|
if(growbuf(&buf, &bufsize, (int)strlen((char *)buf) + CLHDRSIZE)) RETURN(21);
|
||||||
sprintf((char*)buf+strlen((char *)buf), "Content-Length: %"PRIu64"\r\n", contentlength64);
|
sprintf((char*)buf+strlen((char *)buf), "Content-Length: %"PRIu64"\r\n", contentlength64);
|
||||||
hascontent = 1;
|
hascontent = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/proxy.h
20
src/proxy.h
@ -135,6 +135,23 @@ void daemonize(void);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* wolfSSL reserves around 48K of static thread-local storage. glibc counts
|
||||||
|
that against the thread stack, so pthread_create() fails with EINVAL and
|
||||||
|
no thread starts at all. musl places the block next to the stack instead
|
||||||
|
of inside it and needs nothing extra, and OpenSSL has no static TLS.
|
||||||
|
musl identifies itself by no macro of its own, but it does not define
|
||||||
|
__GLIBC__, which any libc header pulled in above would have set.
|
||||||
|
*/
|
||||||
|
#ifndef TLSSTACKSIZE
|
||||||
|
#if defined(__linux__) && !defined(__GLIBC__)
|
||||||
|
#define TLSSTACKSIZE 0
|
||||||
|
#elif defined(WITH_WOLFSSL)
|
||||||
|
#define TLSSTACKSIZE 49152
|
||||||
|
#else
|
||||||
|
#define TLSSTACKSIZE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
size_t threadstacksize(int extra);
|
size_t threadstacksize(int extra);
|
||||||
#endif
|
#endif
|
||||||
@ -352,6 +369,9 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
|
|||||||
int readconfig(FILE * fp);
|
int readconfig(FILE * fp);
|
||||||
void initcommands(void);
|
void initcommands(void);
|
||||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||||
|
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family);
|
||||||
|
int extbindtodevice(struct clientparam *param, SOCKET sock);
|
||||||
|
int intbindtodevice(struct clientparam *param, SOCKET sock);
|
||||||
|
|
||||||
|
|
||||||
uint32_t myrand(void);
|
uint32_t myrand(void);
|
||||||
|
|||||||
@ -830,35 +830,25 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
opt = 1;
|
opt = 1;
|
||||||
if(srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)))perror("setsockopt()");
|
if(srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)))perror("setsockopt()");
|
||||||
|
#else
|
||||||
|
/* A UDP service on Windows answers from a second socket bound to
|
||||||
|
the address it listens on, and Windows only allows that bind
|
||||||
|
when both sockets ask for it. */
|
||||||
|
if(isudp){
|
||||||
|
opt = 1;
|
||||||
|
if(srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)))perror("setsockopt()");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef SO_REUSEPORT
|
#ifdef SO_REUSEPORT
|
||||||
opt = 1;
|
opt = 1;
|
||||||
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined SO_BINDTODEVICE
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
if(srv.ibindtodevice && srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_BINDTODEVICE, srv.ibindtodevice, strlen(srv.ibindtodevice) + 1)) {
|
if(bindtodevice(&srv.so, srv.so.state, sock, srv.ibindtodevice, *SAFAMILY(&srv.intsa))) {
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
return -12;
|
return -12;
|
||||||
}
|
}
|
||||||
#elif defined IP_BOUND_IF
|
|
||||||
if(srv.ibindtodevice){
|
|
||||||
int idx;
|
|
||||||
idx = if_nametoindex(srv.ibindtodevice);
|
|
||||||
if(!idx || (*SAFAMILY(&srv.intsa) == AF_INET && setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)))) {
|
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
|
||||||
return -12;
|
|
||||||
}
|
|
||||||
#ifndef NOIPV6
|
|
||||||
#ifndef IPV6_BOUND_IF
|
|
||||||
#define IPV6_BOUND_IF 125
|
|
||||||
#endif
|
|
||||||
if((*SAFAMILY(&srv.intsa) == AF_INET6 && srv.so._setsockopt(srv.so.state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)))) {
|
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
|
||||||
return -12;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
@ -1012,6 +1002,15 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
setopts(new_sock, srv.cbcsockopts);
|
setopts(new_sock, srv.cbcsockopts);
|
||||||
|
|
||||||
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
||||||
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
|
/* as for a listening socket, an interface that cannot be
|
||||||
|
bound to is not worth retrying */
|
||||||
|
if(bindtodevice(&so, so.state, new_sock, srv.ibindtodevice, *SAFAMILY(&defparam.sincr))) {
|
||||||
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
|
so._closesocket(so.state, new_sock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
||||||
so._closesocket(so.state, new_sock);
|
so._closesocket(so.state, new_sock);
|
||||||
new_sock = INVALID_SOCKET;
|
new_sock = INVALID_SOCKET;
|
||||||
@ -1322,7 +1321,16 @@ void srvfree(struct srvparam * srv){
|
|||||||
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
||||||
srv->cbsock = INVALID_SOCKET;
|
srv->cbsock = INVALID_SOCKET;
|
||||||
srv->service = S_ZOMBIE;
|
srv->service = S_ZOMBIE;
|
||||||
while(srv->child) usleep(SLEEPTIME * 100);
|
/* under the mutex, so the last child has let go of it before it is destroyed */
|
||||||
|
for(;;){
|
||||||
|
struct clientparam *child;
|
||||||
|
|
||||||
|
_3proxy_mutex_lock(&srv->counter_mutex);
|
||||||
|
child = srv->child;
|
||||||
|
_3proxy_mutex_unlock(&srv->counter_mutex);
|
||||||
|
if(!child) break;
|
||||||
|
usleep(SLEEPTIME * 100);
|
||||||
|
}
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(srv->filter){
|
if(srv->filter){
|
||||||
while(srv->nfilters){
|
while(srv->nfilters){
|
||||||
@ -1364,22 +1372,13 @@ void srvfree(struct srvparam * srv){
|
|||||||
void freeparam(struct clientparam * param) {
|
void freeparam(struct clientparam * param) {
|
||||||
if(param->srv){
|
if(param->srv){
|
||||||
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
||||||
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(param->srv->service == S_UDPPM) hashdelete(&udp_table, param);
|
if(param->srv->service == S_UDPPM){
|
||||||
#endif
|
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
||||||
if(param->prev || param->next || param->srv->child == param){
|
hashdelete(&udp_table, param);
|
||||||
if(param->prev){
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
param->prev->next = param->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
param->srv->child = param->next;
|
|
||||||
if(param->next){
|
|
||||||
param->next->prev = param->prev;
|
|
||||||
}
|
|
||||||
(param->srv->childcount)--;
|
|
||||||
}
|
}
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
#endif
|
||||||
}
|
}
|
||||||
if(param->clibuf) free(param->clibuf);
|
if(param->clibuf) free(param->clibuf);
|
||||||
if(param->srvbuf) free(param->srvbuf);
|
if(param->srvbuf) free(param->srvbuf);
|
||||||
@ -1419,6 +1418,24 @@ void freeparam(struct clientparam * param) {
|
|||||||
}
|
}
|
||||||
if(param->connlim) stopconnlims(param);
|
if(param->connlim) stopconnlims(param);
|
||||||
#endif
|
#endif
|
||||||
|
/* Leaving the service comes last. Once its last child is gone, srvfree()
|
||||||
|
frees the service along with its socket functions, filters and mutex,
|
||||||
|
and a close above may have lingered for seconds before getting here. */
|
||||||
|
if(param->srv){
|
||||||
|
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
||||||
|
if(param->prev || param->next || param->srv->child == param){
|
||||||
|
if(param->prev){
|
||||||
|
param->prev->next = param->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
param->srv->child = param->next;
|
||||||
|
if(param->next){
|
||||||
|
param->next->prev = param->prev;
|
||||||
|
}
|
||||||
|
(param->srv->childcount)--;
|
||||||
|
}
|
||||||
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
|
}
|
||||||
if(param->hostname) free(param->hostname);
|
if(param->hostname) free(param->hostname);
|
||||||
if(param->username) free(param->username);
|
if(param->username) free(param->username);
|
||||||
if(param->password) free(param->password);
|
if(param->password) free(param->password);
|
||||||
|
|||||||
@ -159,7 +159,10 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
i = de64(buf,username,255);
|
i = de64(buf,username,255);
|
||||||
if(i < 1) {RETURN(664);}
|
if(i < 1) {RETURN(664);}
|
||||||
username[i] = 0;
|
username[i] = 0;
|
||||||
parseconnusername((char *)username, param, 0, 587);
|
/* The name has to carry the host to connect to, and the answer says
|
||||||
|
whether it did: without one there is nowhere to go, and what follows
|
||||||
|
reads the name as if there were. */
|
||||||
|
if(parseconnusername((char *)username, param, 0, 587)) {RETURN(669);}
|
||||||
socksend(param, param->clisock, (unsigned char *)"334 UGFzc3dvcmQ6\r\n", 18,conf.timeouts[STRING_S]);
|
socksend(param, param->clisock, (unsigned char *)"334 UGFzc3dvcmQ6\r\n", 18,conf.timeouts[STRING_S]);
|
||||||
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
|
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
|
||||||
if(i < 2) {RETURN(665);}
|
if(i < 2) {RETURN(665);}
|
||||||
@ -184,7 +187,7 @@ void * smtppchild(struct clientparam* param) {
|
|||||||
}
|
}
|
||||||
if(i < 3 || *username) {RETURN(668);}
|
if(i < 3 || *username) {RETURN(668);}
|
||||||
username[i] = 0;
|
username[i] = 0;
|
||||||
parseconnusername((char *)username+1, param, 0, 587);
|
if(parseconnusername((char *)username+1, param, 0, 587)) {RETURN(670);}
|
||||||
res = (int)strlen((char *)username+1) + 2;
|
res = (int)strlen((char *)username+1) + 2;
|
||||||
if(res < i){
|
if(res < i){
|
||||||
if(param->extpassword) free(param->extpassword);
|
if(param->extpassword) free(param->extpassword);
|
||||||
|
|||||||
@ -63,7 +63,7 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin,
|
|||||||
if(conf.timetoexit) return EOF;
|
if(conf.timetoexit) return EOF;
|
||||||
res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to);
|
res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to);
|
||||||
if (res<1) return 0;
|
if (res<1) return 0;
|
||||||
sasize = SASIZE(sin);
|
sasize = sizeof(PROXYSOCKADDRTYPE);
|
||||||
do {
|
do {
|
||||||
res = param?param->srv->so._recvfrom(param->sostate, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
|
res = param?param->srv->so._recvfrom(param->sostate, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
|
||||||
} while (res < 0 && (errno == EAGAIN || errno == EINTR));
|
} while (res < 0 && (errno == EAGAIN || errno == EINTR));
|
||||||
|
|||||||
@ -185,6 +185,7 @@ void * sockschild(struct clientparam* param) {
|
|||||||
if(command == 2){
|
if(command == 2){
|
||||||
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
||||||
setopts(param->remsock, param->srv->lissockopts);
|
setopts(param->remsock, param->srv->lissockopts);
|
||||||
|
if(extbindtodevice(param, param->remsock)) {RETURN (12);}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -241,6 +242,7 @@ fflush(stderr);
|
|||||||
#else
|
#else
|
||||||
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
|
if(intbindtodevice(param, param->clisock)) {RETURN (12);}
|
||||||
sin = param->sincl;
|
sin = param->sincl;
|
||||||
*SAPORT(&sin) = 0;
|
*SAPORT(&sin) = 0;
|
||||||
if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
|
if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}
|
||||||
|
|||||||
28
src/ssllib.c
28
src/ssllib.c
@ -84,7 +84,11 @@ static int copy_ext(X509 *dst_cert, X509 *src_cert, int nid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WITH_WOLFSSL
|
#ifndef WITH_WOLFSSL
|
||||||
static int add_ext(X509 *cert, int nid, const char *value)
|
/* issuer is the certificate the extension should describe as the issuer,
|
||||||
|
* which matters for an authority key identifier: it names the key that
|
||||||
|
* signs, not the key being signed.
|
||||||
|
*/
|
||||||
|
static int add_ext_issuer(X509 *cert, X509 *issuer, int nid, const char *value)
|
||||||
{
|
{
|
||||||
X509_EXTENSION *ex;
|
X509_EXTENSION *ex;
|
||||||
X509V3_CTX ctx;
|
X509V3_CTX ctx;
|
||||||
@ -92,10 +96,8 @@ static int add_ext(X509 *cert, int nid, const char *value)
|
|||||||
/* This sets the 'context' of the extensions. */
|
/* This sets the 'context' of the extensions. */
|
||||||
/* No configuration database */
|
/* No configuration database */
|
||||||
X509V3_set_ctx_nodb(&ctx);
|
X509V3_set_ctx_nodb(&ctx);
|
||||||
/* Issuer and subject certs: both the target since it is self signed,
|
/* No request and no CRL */
|
||||||
* no request and no CRL
|
X509V3_set_ctx(&ctx, issuer, cert, NULL, NULL, 0);
|
||||||
*/
|
|
||||||
X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
|
|
||||||
/* value is char * prior to OpenSSL 1.1.0 */
|
/* value is char * prior to OpenSSL 1.1.0 */
|
||||||
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, (char *)value);
|
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, (char *)value);
|
||||||
if (!ex)
|
if (!ex)
|
||||||
@ -105,6 +107,12 @@ static int add_ext(X509 *cert, int nid, const char *value)
|
|||||||
X509_EXTENSION_free(ex);
|
X509_EXTENSION_free(ex);
|
||||||
return err > 0;
|
return err > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_ext(X509 *cert, int nid, const char *value)
|
||||||
|
{
|
||||||
|
/* Issuer and subject: both the target, for a self signed certificate */
|
||||||
|
return add_ext_issuer(cert, cert, nid, value);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||||
@ -199,6 +207,16 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
|||||||
add_ext(dst_cert, NID_basic_constraints, "critical,CA:FALSE");
|
add_ext(dst_cert, NID_basic_constraints, "critical,CA:FALSE");
|
||||||
if(!copy_ext(dst_cert, src_cert, NID_ext_key_usage))
|
if(!copy_ext(dst_cert, src_cert, NID_ext_key_usage))
|
||||||
add_ext(dst_cert, NID_ext_key_usage, "serverAuth");
|
add_ext(dst_cert, NID_ext_key_usage, "serverAuth");
|
||||||
|
/* A verifier following RFC 5280 strictly looks for the issuer through a
|
||||||
|
* key identifier and refuses a certificate carrying none: OpenSSL does
|
||||||
|
* with x509_strict, and Python has since 3.13. The identifiers are
|
||||||
|
* generated rather than copied, so they name the CA signing here
|
||||||
|
* instead of the one that signed upstream. keyid,issuer keeps working
|
||||||
|
* when the CA certificate has no subject key identifier of its own.
|
||||||
|
*/
|
||||||
|
add_ext(dst_cert, NID_subject_key_identifier, "hash");
|
||||||
|
add_ext_issuer(dst_cert, config->CA_cert, NID_authority_key_identifier,
|
||||||
|
"keyid,issuer");
|
||||||
#else
|
#else
|
||||||
copy_ext(dst_cert, src_cert, NID_basic_constraints);
|
copy_ext(dst_cert, src_cert, NID_basic_constraints);
|
||||||
copy_ext(dst_cert, src_cert, NID_ext_key_usage);
|
copy_ext(dst_cert, src_cert, NID_ext_key_usage);
|
||||||
|
|||||||
@ -121,6 +121,11 @@ int udpbind(struct clientparam *param)
|
|||||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
param->remsock = s;
|
param->remsock = s;
|
||||||
|
if (extbindtodevice(param, param->remsock)) {
|
||||||
|
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||||
|
param->remsock = INVALID_SOCKET;
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
if (param->srv->so._bind(param->sostate, param->remsock,
|
if (param->srv->so._bind(param->sostate, param->remsock,
|
||||||
(struct sockaddr *)¶m->sinsl, SASIZE(¶m->sinsl))) {
|
(struct sockaddr *)¶m->sinsl, SASIZE(¶m->sinsl))) {
|
||||||
*SAPORT(¶m->sinsl) = 0;
|
*SAPORT(¶m->sinsl) = 0;
|
||||||
@ -284,6 +289,12 @@ int udpsockmap(struct clientparam *param, int timeo)
|
|||||||
}
|
}
|
||||||
default: return 997;
|
default: return 997;
|
||||||
}
|
}
|
||||||
|
/* As for TCP requests, a literal address is the host name,
|
||||||
|
otherwise an ACL with host names only matches any address */
|
||||||
|
if (!dstname) {
|
||||||
|
myinet_ntop(*SAFAMILY(&dst), SAADDR(&dst), dstnamebuf, sizeof(dstnamebuf));
|
||||||
|
dstname = dstnamebuf;
|
||||||
|
}
|
||||||
memcpy(SAPORT(&dst), base + i, 2);
|
memcpy(SAPORT(&dst), base + i, 2);
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#define VERSION "3proxy-0.9.9"
|
#define VERSION "3proxy-0.9.9.1"
|
||||||
#endif
|
#endif
|
||||||
#ifndef BUILDDATE
|
#ifndef BUILDDATE
|
||||||
#define BUILDDATE ""
|
#define BUILDDATE "261010165717"
|
||||||
#endif
|
#endif
|
||||||
#define MAJOR3PROXY 0
|
#define MAJOR3PROXY 0
|
||||||
#define SUBMAJOR3PROXY 9
|
#define SUBMAJOR3PROXY 9
|
||||||
#define MINOR3PROXY 9
|
#define MINOR3PROXY 9
|
||||||
#define SUBMINOR3PROXY 0
|
#define SUBMINOR3PROXY 1
|
||||||
#define RELEASE3PROXY "3proxy-0.9.9(" BUILDDATE ")\0"
|
#define RELEASE3PROXY "3proxy-0.9.9.1(" BUILDDATE ")\0"
|
||||||
#ifndef YEAR3PROXY
|
#ifndef YEAR3PROXY
|
||||||
#define YEAR3PROXY "2026"
|
#define YEAR3PROXY "2026"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user