Skip to content

Commit 65b9cb0

Browse files
authored
Merge pull request #15 from pseusys/feat/testing-and-evaluation
Testing and evaluation
2 parents 89d0a64 + d5b57af commit 65b9cb0

148 files changed

Lines changed: 4515 additions & 272 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/test_matrix.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set -uo pipefail
88

99
# Treat every compiler warning as an error, matching the default behaviour of
1010
# actions-rust-lang/setup-rust-toolchain on GitHub runners.
11-
export RUSTFLAGS="${RUSTFLAGS:+$RUSTFLAGS }-D warnings"
11+
export RUSTFLAGS="${RUSTFLAGS:+${RUSTFLAGS} }-D warnings"
1212

1313
CRYPTO_IMPLS=(fast_software fast_hardware full_software full_hardware)
1414
PROTOCOL_PARTS=(server client "server,client")
@@ -50,7 +50,7 @@ run_step() {
5050
local rc=$?
5151
echo "::endgroup::"
5252
failures+=("${phase}: ${label}")
53-
return $rc
53+
return "${rc}"
5454
fi
5555
}
5656

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ concurrency:
1616
jobs:
1717
typhoon-build:
1818
name: Build and Run TYPHOON Binaries and Examples
19-
runs-on: ubuntu-24.04
19+
runs-on: ubuntu-latest
2020

2121
steps:
2222
- name: Checkout 🛎️

.github/workflows/lint.yaml

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,80 @@ on:
77
push:
88
paths:
99
- 'typhoon/**'
10-
- '**.md'
10+
- 'evaluation/**'
1111
- '.github/workflows/lint.yaml'
12+
- '.shellcheckrc'
13+
- '**.md'
14+
- '**.go'
1215

1316
concurrency:
1417
group: ${{ github.workflow }}-${{ github.ref }}
1518
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
1619

1720
jobs:
18-
typhoon-lint:
19-
name: Lint TYPHOON Crate and Docs
20-
runs-on: ubuntu-24.04
21+
all-lint:
22+
name: Lint All the Code
23+
runs-on: ubuntu-latest
2124

2225
steps:
2326
- name: Checkout 🛎️
2427
uses: actions/checkout@v4
2528

29+
- name: Lint markdown 📝
30+
uses: DavidAnson/markdownlint-cli2-action@v19
31+
with:
32+
globs: '**/*.md'
33+
34+
- name: Check shell scripts 🐚
35+
uses: ludeeus/action-shellcheck@2.0.0
36+
with:
37+
scandir: "."
38+
env:
39+
SHELLCHECK_OPTS: -s bash -e SC2034
40+
41+
- name: Check Dockerfile configuration 📦
42+
uses: hadolint/hadolint-action@v3.1.0
43+
with:
44+
recursive: true
45+
config: evaluation/.hadolint.yaml
46+
2647
- name: Setup Rust 🦀
2748
uses: actions-rust-lang/setup-rust-toolchain@v1
2849
with:
29-
toolchain: "1.89.0"
50+
toolchain: nightly
3051
components: rustfmt, clippy
3152
rust-src-dir: typhoon
3253
override: true
3354

3455
- name: Check formatting 🎨
35-
working-directory: typhoon
36-
run: cargo fmt --check
56+
run: |
57+
cd typhoon && cargo fmt --check
58+
cd ../evaluation/protocols/typhoon && cargo fmt --check
59+
cd ../wireguard_daita/machines-printer && cargo fmt --check
3760
3861
- name: Run clippy 📎
3962
working-directory: typhoon
40-
run: cargo clippy -- -D warnings
63+
run: cargo clippy
4164

42-
- name: Lint markdown 📝
43-
uses: DavidAnson/markdownlint-cli2-action@v19
65+
- name: Setup Python 🐍
66+
uses: actions/setup-python@v6.2.0
4467
with:
45-
globs: '**/*.md'
68+
python-version: "3.12"
69+
70+
- name: Check Python code 📜
71+
uses: astral-sh/ruff-action@v3
72+
with:
73+
args: "check --config evaluation/pyproject.toml evaluation/src evaluation/protocols"
74+
75+
- name: Setup Go 🐹
76+
uses: actions/setup-go@v5
77+
with:
78+
go-version: "1.22"
79+
80+
- name: Lint Go (wireguard_daita) 🔍
81+
working-directory: evaluation/protocols/wireguard_daita/wg-daita
82+
run: |
83+
git clone --depth=1 --branch mullvad https://github.com/mullvad/wireguard-go ../wireguard-go
84+
go install honnef.co/go/tools/cmd/staticcheck@latest
85+
go mod tidy
86+
staticcheck -tags daita ./...

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ typhoon/target
1010
# Tests:
1111

1212
typhoon/.test_keys
13+
14+
# Evaluation:
15+
16+
evaluation/protocols/wireguard_daita/wg-daita/go.sum
17+
evaluation/protocols/wireguard_daita/wireguard-go

.shellcheckrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
shell=sh
2+
enable=all

PROTOCOL.md

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,43 @@
22

33
This document describes TYPHOON protocol design, goals and proposed implementation in rust.
44

5+
## Design philosophy
6+
7+
TYPHOON is designed to be **flexible and false-fingerprintable** rather than uniformly high-entropy.
8+
9+
Uniform randomness is itself an identifiable pattern, and a static traffic profile — even a well-obfuscated one — can eventually be fingerprinted once an adversary has collected enough samples.
10+
TYPHOON instead aims to look like _different things to different observers_.
11+
Configuration is randomized independently **per [communication channel](#architecture)**, at a finer granularity than a typical connection: even within a single user's activity, different channels can exhibit completely different statistical properties — varying packet sizes, padding strategies, decoy rates, and cleartext header layouts.
12+
Because configuration is re-randomized every time a new channel is established, two sessions between the same endpoints will not share a common traffic profile, even without restarting the server.
13+
14+
The [fake header](#fake-header) mechanism reinforces this: cleartext header fields can be made to resemble headers of arbitrary known protocols, making the traffic false-fingerprintable rather than merely hard to classify.
15+
Combined with independently randomized [fake bodies](#fake-body) and [decoy traffic](#decoy-packets), the result is a protocol whose traffic signature is intentionally unstable and hard to pin to a single classification.
16+
17+
Because no single configuration is universally best, the protocol exposes a set of [tunable constants](#constants-and-defaults) that govern the probability distributions used when generating channel configurations.
18+
Users are encouraged to adapt them to their threat model and performance requirements.
19+
The following scenarios illustrate the trade-off space:
20+
21+
- **Throughput-critical** (e.g. private infrastructure over a trusted or monitored-but-not-filtered link):
22+
minimize or disable padding and decoy traffic. The protocol still provides strong encryption but makes no attempt to disguise statistical properties. Overhead drops to near the cryptographic minimum.
23+
24+
- **Low-latency interactive** (e.g. a remote shell, collaborative editing, or real-time control):
25+
keep packet padding light and decoy injection sparse to avoid adding per-packet delay.
26+
Traffic volume stays close to actual application demand.
27+
28+
- **Protocol-transparent operation** (e.g. managed networks or transit infrastructure that classifies and policies traffic by protocol fingerprint):
29+
enable [fake headers](#fake-header) to match the expected traffic profile of a locally common protocol, and keep decoy traffic at a moderate rate.
30+
The goal is to appear indistinguishable from permitted traffic rather than to resist deep analysis.
31+
32+
- **High-security / traffic-analysis-resistant** (e.g. communicating under active network surveillance):
33+
maximize padding, decoy traffic rates, and fake-header randomization.
34+
Overhead increases substantially, but the traffic becomes hardest to characterize, correlate, or block.
35+
36+
- **Default (balanced)**:
37+
a random mix of configurations is chosen per channel at startup, producing varied traffic that resists classification without being tuned for any single adversary model.
38+
39+
The defaults documented throughout this specification represent a reasonable starting point for the balanced mode and are not optimized for any particular scenario.
40+
Explicit configuration always takes precedence over the defaults.
41+
542
## Assumptions and limitations
643

744
There is one important assumption, required for proceeding with this protocol.
@@ -65,7 +102,7 @@ While it is technically possible for client flow managers to operate using diffe
65102
◄──────────────── wire packet (left = start) ───────────────────►
66103
67104
┌───────────────┬───────────────┬───────────────────┬─────────────┐
68-
Fake Body │ Fake Header │ Encrypted Payload │ Encrypted │
105+
│ Fake Header Fake Body │ Encrypted Payload │ Encrypted │
69106
│ see below │ see below │ (data/hs packets) │ Tailor │
70107
│ (optional) │ (optional) │ variable len │ fixed len │
71108
└───────────────┴───────────────┴───────────────────┴─────────────┘
@@ -134,12 +171,12 @@ It can be either empty, random or constant:
134171
- `empty`: body is always empty, `0` bytes length.
135172
- `random`: body length is random, it is bound between `TYPHOON_FAKE_BODY_LENGTH_MIN` and `TYPHOON_FAKE_BODY_LENGTH_MAX` constant values, making all the packets different in size.
136173
- `service`: same as `random`, but is only applied to [health check](#health-check-packets) and [handshake](#handshake-packets) packets.
137-
- `constant`: body length depends on the lengths of the other packet parts and complement them to a constant size.
174+
- `constant`: body length depends on the lengths of the other packet parts and complement them to a constant size equal to `TYPHOON_FAKE_BODY_CONSTANT_LENGTH` (clamped to `[TYPHOON_FAKE_BODY_LENGTH_MIN, MTU]`).
138175

139176
> Handling `constant` body length might not be trivial, as it imposes a strict limit on packet data contents length.
140177
> TYPHOON protocol specifically does not support data fragmentation, so `constant` body length just won't have any effect if real packet body length is not always strictly limited.
141178
142-
By default, fake body mode is chosen with equal probability for every option except for `service`, which is `TYPHOON_FAKE_BODY_SERVICE_PROBABILITY` heavier than the others.
179+
By default, fake body mode is chosen with equal probability for every option except for `random`, which is `TYPHOON_FAKE_BODY_RANDOM_PROBABILITY` heavier than the others.
143180

144181
### Fake header
145182

@@ -431,7 +468,7 @@ Even though replication is only applied to the decoy packets, it does not result
431468
Also note that only the decoy packet "bodies" are replicated, while [fake headers](#fake-header) and [fake bodies](#fake-body) are generated anew; this represents lower-level protocol headers.
432469

433470
Packet duplicates are sent with a probability within `TYPHOON_DECOY_REPLICATION_PROBABILITY_MIN` and `TYPHOON_DECOY_REPLICATION_PROBABILITY_MAX`, selected upon a flow manager initialization.
434-
After the first duplication, the subsequent duplication probability is multiplied by `TYPHOON_DECOY_REPLICATION_PROBABILITY_REDUCE`, becoming effectively lower.
471+
After the first duplication, the subsequent duplication probability is divided by `TYPHOON_DECOY_REPLICATION_PROBABILITY_REDUCE`, becoming effectively lower.
435472
Packet duplicates are sent within `TYPHOON_DECOY_REPLICATION_DELAY_MIN` and `TYPHOON_DECOY_REPLICATION_DELAY_MAX` milliseconds since the original packet departure.
436473

437474
The replication mode can have these values:
@@ -667,11 +704,11 @@ For the packets going from client to server, tailors are encrypted using the fol
667704
3. Client performs X25519 key exchange using `EphSecKey` and `OPK`, deriving a shared secret (`ShrSec`).
668705
4. Client obfuscates the `EphPubKey` using [`anonymous` encryption](#anonymous-encryption) (the key is derived using `BLAKE3` from concatenation of `OPK` and `Nnc`), producing `EphPubKeyObf`.
669706
5. Client encrypts the `Tailor` using [marshalling encryption](#marshalling-encryption) using `BLAKE3` on `ShrSec` as key and `Nnc` as additional data, producing `TailorEnc`.
670-
6. Client constructs the encrypted tail by concatenating `Nnc`, `EphPubKeyObf` and `TailorEnc`.
707+
6. Client constructs the encrypted tail by concatenating `TailorEnc`, `EphPubKeyObf` and `Nnc`.
671708

672709
The tailors are decrypted using the following steps:
673710

674-
0. Server extracts `Nnc`, `EphPubKeyObf` and `TailorEnc` from the client message.
711+
0. Server extracts `TailorEnc`, `EphPubKeyObf` and `Nnc` from the client message.
675712
1. Server deobfuscates the `EphPubKeyObf` using [`anonymous` encryption](#anonymous-encryption) (the key is derived using `BLAKE3` from concatenation of `OPK` and `Nnc`), producing `EphPubKey`.
676713
2. Server performs X25519 key exchange using `EphPubKey` and `OSK`, deriving a shared secret (`ShrSec`).
677714
3. Server decrypts the `TailorEnc` using [marshalling encryption](#marshalling-encryption) using `BLAKE3` on `ShrSec` as key and `Nnc` as additional data, producing `Tailor`.
@@ -961,11 +998,12 @@ These constants are used in some of the protocol values computation:
961998

962999
| Constant | Meaning | Default |
9631000
| --- | --- | :---: |
964-
| `TYPHOON_FAKE_BODY_LENGTH_MIN` | Minimum length of the fake body random byte string | `0` |
965-
| `TYPHOON_FAKE_BODY_LENGTH_MAX` | Maximum length of the fake body random byte string | `256` |
966-
| `TYPHOON_FAKE_BODY_SERVICE_PROBABILITY` | Multiplier of `service` fake body mode probability | `5` |
1001+
| `TYPHOON_FAKE_BODY_LENGTH_MIN` | Minimum length of the fake body random byte string | `32` |
1002+
| `TYPHOON_FAKE_BODY_LENGTH_MAX` | Maximum length of the fake body random byte string | `512` |
1003+
| `TYPHOON_FAKE_BODY_CONSTANT_LENGTH` | Target packet length for `constant` fake body mode; clamped to `[FAKE_BODY_LENGTH_MIN, MTU]` | `1500` |
1004+
| `TYPHOON_FAKE_BODY_RANDOM_PROBABILITY` | Multiplier of `random` fake body mode probability | `3` |
9671005
| `TYPHOON_FAKE_HEADER_LENGTH_MIN` | Minimum length of the fake header structure | `4` |
968-
| `TYPHOON_FAKE_HEADER_PROBABILITY` | Probability of fake header presence | `0.35` |
1006+
| `TYPHOON_FAKE_HEADER_PROBABILITY` | Probability of fake header presence | `0.6` |
9691007
| `TYPHOON_FAKE_HEADER_LENGTH_MAX` | Maximum length of the fake header structure | `32` |
9701008
| `TYPHOON_HEALTH_CHECK_NEXT_IN_MIN` | Minimum delay between health checking packets | `64000` |
9711009
| `TYPHOON_HEALTH_CHECK_NEXT_IN_MAX` | Maximum delay between health checking packets | `256000` |
@@ -981,26 +1019,26 @@ These constants are used in some of the protocol values computation:
9811019
| `TYPHOON_RTT_MIN` | Minimum RTT value (in milliseconds) | `200` |
9821020
| `TYPHOON_RTT_MAX` | Maximum RTT value (in milliseconds) | `8000` |
9831021
| `TYPHOON_DECOY_REFERENCE_PACKET_RATE_DEFAULT` | Default reference packet rate (in milliseconds) | `200` |
984-
| `TYPHOON_DECOY_CURRENT_PACKET_RATE_DEFAULT` | Default current packet rate (in milliseconds) | `200` |
1022+
| `TYPHOON_DECOY_CURRENT_PACKET_RATE_DEFAULT` | Default current packet rate (in milliseconds) | `1` |
9851023
| `TYPHOON_DECOY_CURRENT_BYTE_RATE_DEFAULT` | Default reference byte rate (in bytes) | `5000` |
9861024
| `TYPHOON_DECOY_BYTE_RATE_CAP` | Maximum bytes that can be sent in a flow per second | `1000000` |
9871025
| `TYPHOON_DECOY_BYTE_RATE_FACTOR` | Multiplier of bytes per second cap for bursts | `3` |
9881026
| `TYPHOON_DECOY_CURRENT_ALPHA` | Current byte rate calculation multiplier (updates fast) | `0.05` |
9891027
| `TYPHOON_DECOY_REFERENCE_ALPHA` | Reference byte rate calculation multiplier (updates slowly) | `0.001` |
990-
| `TYPHOON_DECOY_LENGTH_MAX` | Maximum length of a decoy packet | `1024` |
1028+
| `TYPHOON_DECOY_LENGTH_MAX` | Maximum length of a decoy packet | `512` |
9911029
| `TYPHOON_DECOY_LENGTH_MIN` | Minimum length of a decoy packet | `16` |
9921030
| `TYPHOON_DECOY_BASE_RATE_RND` | Randomization jitter for decoy modes | `0.25` |
9931031
| `TYPHOON_DECOY_HEAVY_BASE_RATE` | Base rate of the heavy decoy mode | `0.05` |
9941032
| `TYPHOON_DECOY_HEAVY_QUIETNESS_FACTOR` | Quietness score factor that is used for heavy decoy mode rate calculation | `3` |
9951033
| `TYPHOON_DECOY_HEAVY_DELAY_MIN` | Minimum delay for heavy decoy mode (in milliseconds) | `5000` |
996-
| `TYPHOON_DECOY_HEAVY_DELAY_MAX` | Maximum delay for heavy decoy mode (in milliseconds) | `120000` |
1034+
| `TYPHOON_DECOY_HEAVY_DELAY_MAX` | Maximum delay for heavy decoy mode (in milliseconds) | `300000` |
9971035
| `TYPHOON_DECOY_HEAVY_DELAY_DEFAULT` | Default delay for heavy decoy mode (in milliseconds) | `64000` |
9981036
| `TYPHOON_DECOY_HEAVY_BASE_LENGTH` | The size of a heavy decoy mode packet (as a fraction of MTU) | `0.7` |
9991037
| `TYPHOON_DECOY_HEAVY_QUIETNESS_LENGTH` | The size of a heavy decoy mode packet (multiplied by quietness index) | `0.3` |
10001038
| `TYPHOON_DECOY_HEAVY_DECOY_LENGTH_FACTOR` | Random heavy decoy mode packet length jitter | `0.8` |
10011039
| `TYPHOON_DECOY_NOISY_BASE_RATE` | Base rate of the noisy decoy mode | `3` |
10021040
| `TYPHOON_DECOY_NOISY_DELAY_MIN` | Minimum delay for noisy decoy mode (in milliseconds) | `10` |
1003-
| `TYPHOON_DECOY_NOISY_DELAY_MAX` | Maximum delay for noisy decoy mode (in milliseconds) | `1000` |
1041+
| `TYPHOON_DECOY_NOISY_DELAY_MAX` | Maximum delay for noisy decoy mode (in milliseconds) | `2000` |
10041042
| `TYPHOON_DECOY_NOISY_DELAY_DEFAULT` | Default delay for noisy decoy mode (in milliseconds) | `500` |
10051043
| `TYPHOON_DECOY_NOISY_DECOY_LENGTH_MIN` | Minimum packet size for noisy decoy mode (in bytes) | `128` |
10061044
| `TYPHOON_DECOY_NOISY_DECOY_LENGTH_JITTER` | Random noisy decoy mode packet length jitter multiplier | `0.3` |
@@ -1009,7 +1047,7 @@ These constants are used in some of the protocol values computation:
10091047
| `TYPHOON_DECOY_SPARSE_JITTER` | Delay jitter for sparse decoy mode | `0.15` |
10101048
| `TYPHOON_DECOY_SPARSE_DELAY_FACTOR` | Reference delay of the sparse decoy mode multiplier | `3` |
10111049
| `TYPHOON_DECOY_SPARSE_DELAY_MIN` | Minimum delay for sparse decoy mode (in milliseconds) | `20` |
1012-
| `TYPHOON_DECOY_SPARSE_DELAY_MAX` | Maximum delay for sparse decoy mode (in milliseconds) | `150` |
1050+
| `TYPHOON_DECOY_SPARSE_DELAY_MAX` | Maximum delay for sparse decoy mode (in milliseconds) | `2000` |
10131051
| `TYPHOON_DECOY_SPARSE_DELAY_DEFAULT` | Default delay for sparse decoy mode (in milliseconds) | `100` |
10141052
| `TYPHOON_DECOY_SPARSE_LENGTH_FACTOR` | Mean multiplier for sparse decoy mode packet length computation | `120` |
10151053
| `TYPHOON_DECOY_SPARSE_LENGTH_SIGMA` | Random sparse decoy mode packet length jitter | `20` |
@@ -1021,7 +1059,7 @@ These constants are used in some of the protocol values computation:
10211059
| `TYPHOON_DECOY_SMOOTH_JITTER` | Delay jitter for smooth decoy mode | `0.2` |
10221060
| `TYPHOON_DECOY_SMOOTH_DELAY_FACTOR` | Reference delay of the smooth decoy mode multiplier | `2` |
10231061
| `TYPHOON_DECOY_SMOOTH_DELAY_MIN` | Minimum delay for smooth decoy mode (in milliseconds) | `300` |
1024-
| `TYPHOON_DECOY_SMOOTH_DELAY_MAX` | Maximum delay for smooth decoy mode (in milliseconds) | `10000` |
1062+
| `TYPHOON_DECOY_SMOOTH_DELAY_MAX` | Maximum delay for smooth decoy mode (in milliseconds) | `300000` |
10251063
| `TYPHOON_DECOY_SMOOTH_DELAY_DEFAULT` | Default delay for smooth decoy mode (in milliseconds) | `5000` |
10261064
| `TYPHOON_DECOY_SMOOTH_LENGTH_MIN` | Minimum packet size for smooth decoy mode (in bytes) | `48` |
10271065
| `TYPHOON_DECOY_SMOOTH_LENGTH_MAX` | Maximum packet size for smooth decoy mode (in bytes) | `512` |
@@ -1140,7 +1178,7 @@ Getters (`flags`, `code`, `time`, `packet_number`, `payload_length`, `identity`)
11401178
The `flow` module owns the UDP send/receive paths and decoy injection.
11411179

11421180
`ClientFlowManager<T, AE>` holds one UDP socket (connected to a server address) and one `Box<dyn DecoyProvider>`.
1143-
Its send path prepends fake body + fake header and appends the encrypted tailor before writing to the socket.
1181+
Its send path prepends fake header + fake body and appends the encrypted tailor before writing to the socket.
11441182
Its receive path strips those same regions after reading from the socket.
11451183

11461184
`ServerFlowManager<T, AE>` manages a pool of `SO_REUSEPORT` sockets and a per-client address table (`Arc<RwLock<HashMap<T, SocketAddr>>>`).

evaluation/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Python
2+
__pycache__/
3+
*.pyc
4+
*.pyo
5+
.venv/
6+
dist/
7+
*.egg-info/
8+
9+
## Poetry
10+
poetry.lock
11+
12+
## Capture results (pcaps can be hundreds of MB)
13+
results/

evaluation/.hadolint.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ignored:
2+
- DL3007 # Docker image tag pins — eval images, not production
3+
- DL3008 # apt-get version pins — eval images, not production
4+
- DL3013 # pip version pins — eval images

evaluation/chaos/Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM ghcr.io/alexei-led/pumba-alpine-nettools:latest
2+
3+
COPY entrypoint.sh /entrypoint.sh
4+
RUN chmod +x /entrypoint.sh
5+
6+
ENTRYPOINT ["/entrypoint.sh"]

evaluation/chaos/entrypoint.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
set -eu
3+
CHAOS_DELAY_MS="${CHAOS_DELAY_MS:-100}"
4+
CHAOS_JITTER_MS="${CHAOS_JITTER_MS:-30}"
5+
CHAOS_LOSS_PCT="${CHAOS_LOSS_PCT:-2}"
6+
7+
_addrs_tmp="/tmp/typhoon_right_if_$$"
8+
ip -o addr show > "${_addrs_tmp}"
9+
RIGHT_IF=$(awk '/172[.]21[.]0[.]2\//{print $2;exit}' "${_addrs_tmp}")
10+
rm -f "${_addrs_tmp}"
11+
tc qdisc del dev "${RIGHT_IF}" root 2>/dev/null || true
12+
tc qdisc add dev "${RIGHT_IF}" root netem limit 200000 \
13+
delay "${CHAOS_DELAY_MS}ms" "${CHAOS_JITTER_MS}ms" \
14+
loss "${CHAOS_LOSS_PCT}%"
15+
16+
exec sleep infinity

0 commit comments

Comments
 (0)