Сборка: добавить production packaging flow через .deb
Добавлен package-режим в tools/build.sh: --package, --dist-dir, --version. Реализована сборка Debian-пакета, metadata/control, postinst/postrm и SHA256SUMS. Установочные пути унифицированы под /usr/sbin и /lib/systemd/system для production-модели.
This commit is contained in:
@@ -20,6 +20,42 @@ Production reboot path — только встроенный scheduler в [`traf
|
||||
|
||||
Важно: ничего из legacy-деревьев не устанавливается, не вызывается и не требуется для runtime пути `awg2-harness`.
|
||||
|
||||
## Production deployment model
|
||||
|
||||
AWG2 Harness собирается на отдельной Debian 13 amd64 build-machine.
|
||||
|
||||
Production Amnezia-хост **не должен** требовать Rust, cargo, clippy, source tree и legacy bash-скрипты. На production-хост переносится готовый Debian-пакет и вручную подготовленный `/etc/awg2-harness/config.toml`.
|
||||
|
||||
Build machine:
|
||||
|
||||
```bash
|
||||
./tools/build.sh --prepare-build-env --bootstrap-rust --yes
|
||||
./tools/build.sh --package
|
||||
sha256sum -c dist/SHA256SUMS
|
||||
```
|
||||
|
||||
Копирование на production host:
|
||||
|
||||
```bash
|
||||
scp dist/awg2-harness_*_amd64.deb root@vpn-host:/root/
|
||||
scp config.toml root@vpn-host:/root/awg2-harness.config.toml
|
||||
```
|
||||
|
||||
Production host:
|
||||
|
||||
```bash
|
||||
apt install ./awg2-harness_*_amd64.deb
|
||||
install -d -m 0755 /etc/awg2-harness
|
||||
install -m 0644 /root/awg2-harness.config.toml /etc/awg2-harness/config.toml
|
||||
awg2-harness validate-config --config /etc/awg2-harness/config.toml
|
||||
awg2-harness apply-limits --config /etc/awg2-harness/config.toml
|
||||
awg2-harness apply-firewall --config /etc/awg2-harness/config.toml
|
||||
awg2-harness status --config /etc/awg2-harness/config.toml
|
||||
systemctl enable --now awg2-harness.service
|
||||
```
|
||||
|
||||
Ничего из [`Amnezia limits (old bash)/`](Amnezia%20limits%20(old%20bash)/) и [`reboot_module/`](reboot_module/) не запускается в production-пути.
|
||||
|
||||
Основная документация:
|
||||
|
||||
- [`docs/MIGRATION.md`](docs/MIGRATION.md) — исправленная миграционная стратегия bash → Rust multi-orchestrator.
|
||||
|
||||
@@ -7,7 +7,7 @@ Requires=docker.service
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/local/bin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
ExecStart=/usr/sbin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
|
||||
@@ -115,3 +115,17 @@
|
||||
- [ ] Известно, как остановить `awg2-harness.service`.
|
||||
- [ ] Известно, как вернуть `amnezia-tc.service` и `amnezia-tc-watcher.service`.
|
||||
- [ ] Rollback проверен на тестовом сервере.
|
||||
|
||||
## K. Packaging / release
|
||||
|
||||
- [ ] Package собирается на отдельной Debian 13 amd64 build-machine.
|
||||
- [ ] Production host не требует Rust/cargo/source tree.
|
||||
- [ ] `./tools/build.sh --package` создаёт `dist/awg2-harness_<version>_amd64.deb`.
|
||||
- [ ] `dist/SHA256SUMS` валидирует checksum пакета.
|
||||
- [ ] Пакет ставит бинарь в `/usr/sbin/awg2-harness`.
|
||||
- [ ] Пакет ставит unit в `/lib/systemd/system/awg2-harness.service`.
|
||||
- [ ] Пакет не устанавливает `/etc/awg2-harness/config.toml` автоматически.
|
||||
- [ ] Пакет не включает/не стартует сервис автоматически.
|
||||
- [ ] `apt install ./awg2-harness_<version>_amd64.deb` проходит на clean Debian 13 Amnezia host.
|
||||
- [ ] После ручной установки config `awg2-harness validate-config` проходит.
|
||||
- [ ] Сервис стартует только после явного `systemctl enable --now awg2-harness.service`.
|
||||
|
||||
@@ -26,7 +26,7 @@ It does not replace Amnezia. It controls the surrounding system state that the o
|
||||
One systemd service runs:
|
||||
|
||||
```bash
|
||||
/usr/local/bin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
/usr/sbin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
```
|
||||
|
||||
The daemon starts as root and keeps running. On startup it performs initial reconcile. During runtime it reacts to Docker events and also runs a periodic reconcile loop.
|
||||
@@ -311,7 +311,7 @@ table inet awg2_harness {
|
||||
|
||||
Target namespace: the same Amnezia network namespace where `tc` shaping is applied. Do not assume the initial host namespace sees original peer source addresses. If Amnezia performs NAT inside the container namespace, the host Docker bridge may only see the container address, not `10.8.1.x`.
|
||||
|
||||
Default threshold: `200` concurrent flows per peer IP. `250` is the conservative compatibility setting if there are complaints from unusually connection-heavy WebSocket/WebRTC/trading-browser workloads. `150` is more aggressive and should only be used after real traffic observation.
|
||||
Default threshold: `100` concurrent flows per peer IP. `150` is the conservative compatibility setting if there are complaints from unusually connection-heavy WebSocket/WebRTC/trading-browser workloads. `70` is more aggressive and should only be used after real traffic observation.
|
||||
|
||||
Rule placement: use `forward` hook with priority `filter` or any priority after conntrack lookup. Restrict evaluation to `ct state new` so established flows continue normally and only new flow attempts beyond the threshold are dropped.
|
||||
|
||||
|
||||
+37
-120
@@ -1,156 +1,73 @@
|
||||
# Установка AWG2 Harness на production-хост
|
||||
# Installation
|
||||
|
||||
## 1. Предусловия
|
||||
## Deployment contract
|
||||
|
||||
Хост:
|
||||
- Build выполняется на отдельной Debian 13 amd64 build-machine.
|
||||
- Production-хост получает готовый Debian-пакет.
|
||||
- На production-хосте не требуются Rust/cargo/source tree.
|
||||
- Amnezia должна быть уже установлена и работать через Docker.
|
||||
- Production-конфиг создаётся вручную; [`config.example.toml`](../config.example.toml) не копируется автоматически как боевой конфиг.
|
||||
|
||||
- Debian 13 amd64;
|
||||
- root-доступ;
|
||||
- SSH настроен заранее;
|
||||
- AmneziaWG/AWG 2.0 установлена официальным способом;
|
||||
- контейнер Amnezia запускается через Docker;
|
||||
- сервер выделенный, без соседних сервисов, чьи сетевые правила нужно сохранять.
|
||||
## A. Build machine
|
||||
|
||||
На хосте должны быть доступны:
|
||||
|
||||
```bash
|
||||
docker
|
||||
systemctl
|
||||
ip
|
||||
tc
|
||||
wg
|
||||
nsenter
|
||||
modprobe
|
||||
nft
|
||||
```
|
||||
|
||||
`tc/ip/wg` внутри контейнера полезны для fallback, но целевая модель — host tools + вход в network namespace контейнера.
|
||||
|
||||
## 2. Сборка бинаря
|
||||
|
||||
Сборку лучше выполнять на отдельной build-машине с тем же целевым ABI.
|
||||
### A1. Подготовка build environment
|
||||
|
||||
```bash
|
||||
./tools/build.sh --prepare-build-env --bootstrap-rust --yes
|
||||
./tools/build.sh
|
||||
```
|
||||
|
||||
Альтернатива (ручной запуск cargo из корня репозитория):
|
||||
### A2. Build и тесты
|
||||
|
||||
```bash
|
||||
cargo build --locked --manifest-path traffic_core/Cargo.toml --release
|
||||
./tools/build.sh --build
|
||||
```
|
||||
|
||||
Проверки перед переносом:
|
||||
### A3. Сборка пакета
|
||||
|
||||
```bash
|
||||
cargo fmt --manifest-path traffic_core/Cargo.toml --all --check
|
||||
cargo clippy --locked --manifest-path traffic_core/Cargo.toml --all-targets -- -D warnings
|
||||
cargo test --locked --manifest-path traffic_core/Cargo.toml --release
|
||||
file traffic_core/target/release/awg2-harness
|
||||
ldd traffic_core/target/release/awg2-harness
|
||||
./tools/build.sh --package
|
||||
sha256sum -c dist/SHA256SUMS
|
||||
```
|
||||
|
||||
## 3. Установка файлов
|
||||
## B. Transfer artifacts
|
||||
|
||||
```bash
|
||||
scp dist/awg2-harness_*_amd64.deb root@vpn-host:/root/
|
||||
scp config.toml root@vpn-host:/root/awg2-harness.config.toml
|
||||
```
|
||||
|
||||
## C. Production host
|
||||
|
||||
### C1. Install package
|
||||
|
||||
```bash
|
||||
apt install ./awg2-harness_*_amd64.deb
|
||||
```
|
||||
|
||||
### C2. Install config
|
||||
|
||||
```bash
|
||||
install -m 0755 traffic_core/target/release/awg2-harness /usr/local/bin/awg2-harness
|
||||
install -d -m 0755 /etc/awg2-harness
|
||||
install -m 0644 config.toml /etc/awg2-harness/config.toml
|
||||
install -m 0644 /root/awg2-harness.config.toml /etc/awg2-harness/config.toml
|
||||
```
|
||||
|
||||
Важно: production-установка **не должна** автоматически копировать [`config.example.toml`](../config.example.toml) как боевой конфиг.
|
||||
Если используется [`tools/build.sh`](../tools/build.sh), режим `--install` завершится ошибкой при отсутствии `/etc/awg2-harness/config.toml`.
|
||||
Режим `--install` копирует только бинарь и unit, выполняет `systemctl daemon-reload`, но не делает `systemctl enable --now`.
|
||||
Сначала подготовьте осознанный production-конфиг вручную.
|
||||
|
||||
Проверка конфига:
|
||||
### C3. Validate and apply
|
||||
|
||||
```bash
|
||||
awg2-harness validate-config --config /etc/awg2-harness/config.toml
|
||||
```
|
||||
|
||||
## 4. Первичное применение traffic topology
|
||||
|
||||
```bash
|
||||
awg2-harness apply-limits --config /etc/awg2-harness/config.toml
|
||||
awg2-harness apply-firewall --config /etc/awg2-harness/config.toml
|
||||
awg2-harness status --config /etc/awg2-harness/config.toml
|
||||
```
|
||||
|
||||
Ожидается:
|
||||
|
||||
- найден контейнер `amnezia-awg2` или `amnezia-awg`;
|
||||
- найден network namespace контейнера;
|
||||
- найден AWG/WG-интерфейс;
|
||||
- найдены peers из `wg show all allowed-ips`;
|
||||
- создана egress topology на AWG/WG-интерфейсе;
|
||||
- создан `ifb0`;
|
||||
- создан ingress redirect в `ifb0`;
|
||||
- на каждого peer есть egress и ingress class/filter;
|
||||
- если anti-torrent включён, в Amnezia netns есть `table inet awg2_harness` и drop counter отображается в status.
|
||||
|
||||
## 5. Настройка swap
|
||||
### C4. Enable daemon
|
||||
|
||||
```bash
|
||||
awg2-harness ensure-swap --config /etc/awg2-harness/config.toml
|
||||
swapon --show
|
||||
cat /proc/sys/vm/swappiness
|
||||
```
|
||||
|
||||
Ожидается `/swapfile` размером 2 ГБ, права `0600`, запись в `/etc/fstab`, низкая склонность к использованию.
|
||||
|
||||
## 6. Установка systemd unit
|
||||
|
||||
`/etc/systemd/system/awg2-harness.service`:
|
||||
|
||||
Reference unit в репозитории: [`awg2-harness.service`](../awg2-harness.service).
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=AWG2 Harness multi-orchestrator
|
||||
After=network-online.target docker.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/local/bin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Активация:
|
||||
|
||||
```bash
|
||||
systemd-analyze verify /etc/systemd/system/awg2-harness.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now awg2-harness.service
|
||||
```
|
||||
|
||||
## 7. Проверка после запуска daemon
|
||||
## D. Manual source-tree install (staging/debug only)
|
||||
|
||||
```bash
|
||||
systemctl status awg2-harness.service
|
||||
journalctl -u awg2-harness.service -n 100 --no-pager
|
||||
awg2-harness status --config /etc/awg2-harness/config.toml
|
||||
```
|
||||
Режим [`./tools/build.sh --install`](../tools/build.sh) предназначен для staging/debug с checkout-репозиторием.
|
||||
|
||||
## 8. Проверка auto-healing
|
||||
|
||||
```bash
|
||||
docker restart amnezia-awg2
|
||||
sleep 30
|
||||
awg2-harness status --config /etc/awg2-harness/config.toml
|
||||
```
|
||||
|
||||
Затем проверить Docker restart и host reboot. После каждого события status должен показывать healthy state без ручного запуска old bash.
|
||||
|
||||
## 9. Rollback
|
||||
|
||||
Production-путь AWG2 Harness не включает возврат к old bash в штатный процесс выкладки.
|
||||
Это **не** основной production deployment path.
|
||||
|
||||
+1
-1
@@ -233,7 +233,7 @@ Requires=docker.service
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/local/bin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
ExecStart=/usr/sbin/awg2-harness daemon --config /etc/awg2-harness/config.toml
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
|
||||
+21
-8
@@ -10,6 +10,10 @@ Unit: [`awg2-harness.service`](../awg2-harness.service).
|
||||
- Debian/Ubuntu (apt-based)
|
||||
- amd64/x86_64
|
||||
|
||||
## Purpose
|
||||
|
||||
Скрипт используется на build-machine для проверки, сборки и упаковки AWG2 Harness.
|
||||
|
||||
## Default mode
|
||||
|
||||
```bash
|
||||
@@ -28,29 +32,38 @@ Unit: [`awg2-harness.service`](../awg2-harness.service).
|
||||
- `--prepare-runtime-env` — установить недостающие runtime-пакеты;
|
||||
- `--bootstrap-rust` — установить rustup и pinned toolchain;
|
||||
- `--build` — запустить build gate явно;
|
||||
- `--package` — собрать Debian-пакет в `dist/`;
|
||||
- `--dist-dir <path>` — директория для release artifacts;
|
||||
- `--version <version>` — переопределить версию пакета;
|
||||
- `--install` — установить бинарь + systemd unit (без enable/start);
|
||||
- `--enable` — `systemctl enable --now awg2-harness.service`;
|
||||
- `--yes` — подтверждение системных изменений (apt/rustup);
|
||||
- `--skip-fmt` — пропустить `cargo fmt --check`;
|
||||
- `--help` — справка.
|
||||
|
||||
## Typical build machine flow
|
||||
## Build machine flow
|
||||
|
||||
```bash
|
||||
./tools/build.sh --prepare-build-env --bootstrap-rust --yes
|
||||
./tools/build.sh
|
||||
./tools/build.sh --build
|
||||
./tools/build.sh --package
|
||||
```
|
||||
|
||||
## Typical production host flow
|
||||
## Production host flow
|
||||
|
||||
В нормальном production deployment **не нужно** клонировать репозиторий на целевой хост.
|
||||
Ставится сгенерированный пакет:
|
||||
|
||||
```bash
|
||||
./tools/build.sh --prepare-runtime-env --yes
|
||||
install -d -m 0755 /etc/awg2-harness
|
||||
install -m 0644 config.toml /etc/awg2-harness/config.toml
|
||||
./tools/build.sh --install
|
||||
./tools/build.sh --enable
|
||||
apt install ./awg2-harness_*_amd64.deb
|
||||
```
|
||||
|
||||
## Manual source-tree install
|
||||
|
||||
`--install` и `--enable` оставлены для staging/debug из checked-out source tree.
|
||||
|
||||
Это **не рекомендуемый** production path.
|
||||
|
||||
## What the script intentionally does not do
|
||||
|
||||
- не устанавливает Docker автоматически;
|
||||
|
||||
+141
-6
@@ -11,12 +11,16 @@ PREPARE_BUILD_ENV=false
|
||||
PREPARE_RUNTIME_ENV=false
|
||||
BOOTSTRAP_RUST=false
|
||||
DO_BUILD=false
|
||||
PACKAGE=false
|
||||
INSTALL=false
|
||||
ENABLE=false
|
||||
YES=false
|
||||
SKIP_FMT=false
|
||||
HAS_ACTION=false
|
||||
|
||||
DIST_DIR="$ROOT_DIR/dist"
|
||||
PACKAGE_VERSION=""
|
||||
|
||||
RUN_AS_ROOT=()
|
||||
|
||||
BUILD_PACKAGES=(
|
||||
@@ -26,6 +30,7 @@ BUILD_PACKAGES=(
|
||||
pkg-config
|
||||
file
|
||||
shellcheck
|
||||
dpkg-dev
|
||||
)
|
||||
|
||||
RUNTIME_PACKAGES=(
|
||||
@@ -46,6 +51,8 @@ Usage:
|
||||
./tools/build.sh --prepare-runtime-env --yes
|
||||
./tools/build.sh --bootstrap-rust --yes
|
||||
./tools/build.sh --build
|
||||
./tools/build.sh --package
|
||||
./tools/build.sh --build --package
|
||||
./tools/build.sh --install
|
||||
./tools/build.sh --enable
|
||||
|
||||
@@ -54,27 +61,45 @@ Flags:
|
||||
--prepare-runtime-env Install missing runtime dependencies via apt
|
||||
--bootstrap-rust Install rustup/toolchain pinned by this repo
|
||||
--build Run build gate (default when no action flags)
|
||||
--package Build Debian package into dist/ (runs build gate by default)
|
||||
--dist-dir <path> Output directory for package artifacts (default: ./dist)
|
||||
--version <version> Override package version (default: read from Cargo.toml)
|
||||
--install Install binary and systemd unit (no enable/start)
|
||||
--enable Enable and start awg2-harness.service
|
||||
--yes Confirm system mutations (apt/rustup)
|
||||
--skip-fmt Skip cargo fmt --check
|
||||
--help Show this help
|
||||
Notes:
|
||||
--install is for manual source-tree installs (staging/debug).
|
||||
Preferred production flow is package-based deployment via apt install ./awg2-harness_<version>_amd64.deb
|
||||
EOF
|
||||
}
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--prepare-build-env) PREPARE_BUILD_ENV=true; HAS_ACTION=true ;;
|
||||
--prepare-runtime-env) PREPARE_RUNTIME_ENV=true; HAS_ACTION=true ;;
|
||||
--bootstrap-rust) BOOTSTRAP_RUST=true; HAS_ACTION=true ;;
|
||||
--build) DO_BUILD=true; HAS_ACTION=true ;;
|
||||
--package) PACKAGE=true; HAS_ACTION=true ;;
|
||||
--dist-dir)
|
||||
[[ $# -ge 2 ]] || { echo "--dist-dir requires value"; exit 1; }
|
||||
DIST_DIR="$2"
|
||||
shift
|
||||
;;
|
||||
--version)
|
||||
[[ $# -ge 2 ]] || { echo "--version requires value"; exit 1; }
|
||||
PACKAGE_VERSION="$2"
|
||||
shift
|
||||
;;
|
||||
--install) INSTALL=true; HAS_ACTION=true ;;
|
||||
--enable) ENABLE=true; HAS_ACTION=true ;;
|
||||
--yes) YES=true ;;
|
||||
--skip-fmt) SKIP_FMT=true ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
*) echo "Unknown arg: $arg"; usage; exit 1 ;;
|
||||
*) echo "Unknown arg: $1"; usage; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ "$HAS_ACTION" == false ]]; then
|
||||
@@ -219,15 +244,121 @@ install_artifacts() {
|
||||
fi
|
||||
|
||||
setup_root_runner
|
||||
"${RUN_AS_ROOT[@]}" install -m 0755 "$TARGET_BIN" /usr/local/bin/awg2-harness
|
||||
"${RUN_AS_ROOT[@]}" install -m 0644 "$ROOT_DIR/awg2-harness.service" /etc/systemd/system/awg2-harness.service
|
||||
"${RUN_AS_ROOT[@]}" install -d -m 0755 /usr/sbin
|
||||
"${RUN_AS_ROOT[@]}" install -m 0755 "$TARGET_BIN" /usr/sbin/awg2-harness
|
||||
"${RUN_AS_ROOT[@]}" install -d -m 0755 /lib/systemd/system
|
||||
"${RUN_AS_ROOT[@]}" install -m 0644 "$ROOT_DIR/awg2-harness.service" /lib/systemd/system/awg2-harness.service
|
||||
|
||||
if command -v systemd-analyze >/dev/null 2>&1; then
|
||||
"${RUN_AS_ROOT[@]}" systemd-analyze verify /etc/systemd/system/awg2-harness.service
|
||||
"${RUN_AS_ROOT[@]}" systemd-analyze verify /lib/systemd/system/awg2-harness.service
|
||||
fi
|
||||
"${RUN_AS_ROOT[@]}" systemctl daemon-reload
|
||||
}
|
||||
|
||||
read_package_version_from_manifest() {
|
||||
awk -F '"' '/^version\s*=\s*"/ { print $2; exit }' "$CRATE_MANIFEST"
|
||||
}
|
||||
|
||||
package_deb() {
|
||||
require_cmd dpkg-deb
|
||||
require_cmd install
|
||||
require_cmd sha256sum
|
||||
require_cmd file
|
||||
require_cmd ldd
|
||||
require_cmd mktemp
|
||||
|
||||
if [[ "$DO_BUILD" != true ]]; then
|
||||
prepare_build_gate
|
||||
fi
|
||||
|
||||
if [[ ! -f "$TARGET_BIN" ]]; then
|
||||
echo "Binary not found after build: $TARGET_BIN"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local version
|
||||
if [[ -n "$PACKAGE_VERSION" ]]; then
|
||||
version="$PACKAGE_VERSION"
|
||||
else
|
||||
version="$(read_package_version_from_manifest)"
|
||||
fi
|
||||
|
||||
if [[ -z "$version" ]]; then
|
||||
echo "Unable to determine package version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local staging
|
||||
staging="$(mktemp -d)"
|
||||
trap 'rm -rf "$staging"' RETURN
|
||||
|
||||
install -d -m 0755 "$staging/DEBIAN"
|
||||
install -d -m 0755 "$staging/usr/sbin"
|
||||
install -d -m 0755 "$staging/lib/systemd/system"
|
||||
install -d -m 0755 "$staging/usr/share/doc/awg2-harness"
|
||||
|
||||
install -m 0755 "$TARGET_BIN" "$staging/usr/sbin/awg2-harness"
|
||||
install -m 0644 "$ROOT_DIR/awg2-harness.service" "$staging/lib/systemd/system/awg2-harness.service"
|
||||
install -m 0644 "$ROOT_DIR/config.example.toml" "$staging/usr/share/doc/awg2-harness/config.example.toml"
|
||||
install -m 0644 "$ROOT_DIR/README.md" "$staging/usr/share/doc/awg2-harness/README.md"
|
||||
install -m 0644 "$ROOT_DIR/docs/INSTALLATION.md" "$staging/usr/share/doc/awg2-harness/INSTALLATION.md"
|
||||
|
||||
cat >"$staging/DEBIAN/control" <<EOF
|
||||
Package: awg2-harness
|
||||
Version: $version
|
||||
Section: net
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Maintainer: AWG2 Harness
|
||||
Depends: libc6, iproute2, wireguard-tools, nftables, kmod, util-linux, procps, systemd
|
||||
Recommends: docker.io
|
||||
Description: Host-side orchestrator for AmneziaWG traffic shaping and lifecycle recovery
|
||||
AWG2 Harness manages AmneziaWG traffic shaping, IFB ingress shaping,
|
||||
nftables anti-torrent guard, reboot scheduling, swap setup and daemonized
|
||||
drift recovery on dedicated Debian hosts.
|
||||
EOF
|
||||
|
||||
cat >"$staging/DEBIAN/postinst" <<'EOF'
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl daemon-reload || true
|
||||
fi
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
cat >"$staging/DEBIAN/postrm" <<'EOF'
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl daemon-reload || true
|
||||
fi
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
chmod 0755 "$staging/DEBIAN/postinst" "$staging/DEBIAN/postrm"
|
||||
|
||||
mkdir -p "$DIST_DIR"
|
||||
local pkg_name
|
||||
pkg_name="awg2-harness_${version}_amd64.deb"
|
||||
local pkg_path
|
||||
pkg_path="$DIST_DIR/$pkg_name"
|
||||
|
||||
dpkg-deb --build "$staging" "$pkg_path"
|
||||
|
||||
(
|
||||
cd "$DIST_DIR"
|
||||
sha256sum "$pkg_name" > SHA256SUMS
|
||||
)
|
||||
|
||||
echo "Package created: $pkg_path"
|
||||
echo "Checksums: $DIST_DIR/SHA256SUMS"
|
||||
}
|
||||
|
||||
enable_service() {
|
||||
require_cmd systemctl
|
||||
setup_root_runner
|
||||
@@ -252,6 +383,10 @@ if [[ "$DO_BUILD" == true ]]; then
|
||||
prepare_build_gate
|
||||
fi
|
||||
|
||||
if [[ "$PACKAGE" == true ]]; then
|
||||
package_deb
|
||||
fi
|
||||
|
||||
if [[ "$INSTALL" == true ]]; then
|
||||
install_artifacts
|
||||
fi
|
||||
|
||||
@@ -290,11 +290,12 @@ fn parse_tc_filter_hits(raw: &str) -> BTreeMap<String, u64> {
|
||||
current_ip = extract_tc_match_ip(t);
|
||||
} else if t.starts_with("Sent ") {
|
||||
if let Some(ip) = current_ip.clone() {
|
||||
let hits = t
|
||||
.split_whitespace()
|
||||
.nth(4)
|
||||
.and_then(|s| s.parse::<u64>().ok())
|
||||
.unwrap_or(0);
|
||||
let hits = parse_sent_packets(t).unwrap_or(0);
|
||||
out.insert(ip, hits);
|
||||
}
|
||||
} else if t.contains(" success ") || t.starts_with("success ") {
|
||||
if let Some(ip) = current_ip.clone() {
|
||||
let hits = parse_success_packets(t).unwrap_or(0);
|
||||
out.insert(ip, hits);
|
||||
}
|
||||
}
|
||||
@@ -302,6 +303,20 @@ fn parse_tc_filter_hits(raw: &str) -> BTreeMap<String, u64> {
|
||||
out
|
||||
}
|
||||
|
||||
fn parse_sent_packets(line: &str) -> Option<u64> {
|
||||
let toks: Vec<&str> = line.split_whitespace().collect();
|
||||
if toks.len() >= 5 && toks[0] == "Sent" && toks[2] == "bytes" && toks[4] == "pkt" {
|
||||
return toks[3].parse::<u64>().ok();
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn parse_success_packets(line: &str) -> Option<u64> {
|
||||
let toks: Vec<&str> = line.split_whitespace().collect();
|
||||
let pos = toks.iter().position(|v| *v == "success")?;
|
||||
toks.get(pos + 1)?.parse::<u64>().ok()
|
||||
}
|
||||
|
||||
fn extract_tc_match_ip(line: &str) -> Option<String> {
|
||||
let toks: Vec<&str> = line.split_whitespace().collect();
|
||||
let pos = toks.iter().position(|v| *v == "match")?;
|
||||
@@ -316,3 +331,37 @@ fn extract_tc_match_ip(line: &str) -> Option<String> {
|
||||
let b4 = u8::from_str_radix(&hex[6..8], 16).ok()?;
|
||||
Some(format!("{b1}.{b2}.{b3}.{b4}"))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{parse_sent_packets, parse_success_packets, parse_tc_filter_hits};
|
||||
|
||||
#[test]
|
||||
fn parse_sent_pkt_counter() {
|
||||
let line = "Sent 12345 bytes 67 pkt (dropped 0, overlimits 0 requeues 0)";
|
||||
assert_eq!(parse_sent_packets(line), Some(67));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_success_counter() {
|
||||
let line = "match 0a080102/ffffffff at 16 success 42";
|
||||
assert_eq!(parse_success_packets(line), Some(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_tc_filter_hits_supports_sent_and_success() {
|
||||
let raw = r#"
|
||||
filter parent 1: protocol ip pref 1 u32 chain 0
|
||||
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800: ht divisor 1
|
||||
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:10 not_in_hw
|
||||
match 0a080102/ffffffff at 16
|
||||
Sent 100 bytes 7 pkt (dropped 0, overlimits 0 requeues 0)
|
||||
filter parent 1: protocol ip pref 1 u32 chain 0 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:11 not_in_hw
|
||||
match 0a080103/ffffffff at 16 success 9
|
||||
"#;
|
||||
|
||||
let map = parse_tc_filter_hits(raw);
|
||||
assert_eq!(map.get("10.8.1.2"), Some(&7));
|
||||
assert_eq!(map.get("10.8.1.3"), Some(&9));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user