Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
cc12bf7
test: retry badssl.com tests up to 5 times to handle transient EOF
smeinecke Mar 18, 2026
63316af
fix: disable connection reuse in test_insecure_skip_verify to prevent…
smeinecke Mar 18, 2026
d556796
fix: skip badssl.com tests on transient network errors instead of fai…
smeinecke Mar 18, 2026
ab4bfdb
Merge pull request #44 from smeinecke/fix/badssl-test-reliability
Danny-Dasilva Apr 27, 2026
9bcffdf
ci(unit-tests): run macOS only for Python 3.13 to ease runner pressur…
Danny-Dasilva Apr 27, 2026
73cad43
ci: add CodeQL analysis, expand dependabot, bump action versions (#47)
Danny-Dasilva Apr 28, 2026
65a4513
fix(transport): lower IdleConnTimeout 90s to 60s to undercut peer kee…
Danny-Dasilva Apr 28, 2026
b16a75e
build(deps): bump softprops/action-gh-release from 2 to 3 (#54)
dependabot[bot] Apr 28, 2026
134279d
build(deps): bump actions/checkout from 4 to 6 (#55)
dependabot[bot] Apr 28, 2026
ccd82d3
build(deps): bump actions/setup-python from 5 to 6 (#56)
dependabot[bot] Apr 28, 2026
ff89cad
build(deps): bump actions/setup-go from 5 to 6 (#57)
dependabot[bot] Apr 28, 2026
28fe1ac
fix(release): build Linux .so targeting glibc 2.17 via zig cc (#41)
smeinecke Apr 28, 2026
062381e
fix(tests): mark badssl.com tests as live; fix CHANGELOG fetch-depth …
Danny-Dasilva Apr 28, 2026
c16714f
fix(transport): propagate enable_connection_reuse=False as DisableKee…
Danny-Dasilva Apr 28, 2026
0c779c8
build(deps): bump github.com/gorilla/websocket in /golang (#62)
dependabot[bot] Apr 28, 2026
84998bf
build(deps): bump github.com/refraction-networking/utls in /golang (#59)
dependabot[bot] Apr 28, 2026
085a0bb
feat(extensions): expose proper utls types for ID 17, 17613, 30032 (#66)
Danny-Dasilva Apr 28, 2026
0712e71
build(deps): bump golang.org/x/net from 0.42.0 to 0.53.0 in /golang (…
dependabot[bot] Apr 28, 2026
984189c
build(deps): bump github.com/quic-go/quic-go in /golang (#60)
dependabot[bot] Apr 28, 2026
fc5c3e4
build(deps): bump github.com/valyala/fasthttp in /benchmarks (#64)
dependabot[bot] Apr 28, 2026
fe25ca7
build(deps): bump github.com/andybalholm/brotli in /golang (#61)
dependabot[bot] Apr 28, 2026
d19a614
build(deps): bump actions/checkout from 4 to 6 (#67)
dependabot[bot] Apr 28, 2026
e12b39b
feat(tests): run live tests against local tlsfingerprint.com Docker i…
Danny-Dasilva May 7, 2026
633710f
fix(go-core): local_address binding, Do() field drops, TLS13AutoRetry…
Danny-Dasilva May 7, 2026
243416a
build(deps): bump github.com/valyala/fasthttp in /benchmarks (#68)
dependabot[bot] May 7, 2026
4d30646
Merge upstream/main into merge/upstream-latest
smeinecke May 14, 2026
5ed3c9a
Merge remote-tracking branch 'upstream/main' into merge/upstream-latest
smeinecke May 14, 2026
2fc01c4
fix(tests): disable connection reuse for httpbin.org to fix live test…
smeinecke May 14, 2026
205fefc
fix(tests): use urlparse hostname check instead of substring match fo…
smeinecke May 14, 2026
b67e448
fix(tests): mark test_large_concurrent_batch as flaky (rate-limited b…
smeinecke May 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 31 additions & 17 deletions .github/workflows/blocking-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,46 @@ jobs:
- name: Install dependencies
run: uv sync --locked --all-extras --dev

- name: Generate TLS certificates for TrackMe
- name: Checkout Danny-Dasilva/tlsfingerprint.com
uses: actions/checkout@v4
with:
repository: Danny-Dasilva/tlsfingerprint.com
ref: master
path: .tlsfingerprint-server

- name: Generate TLS certificates and config
working-directory: .tlsfingerprint-server
run: |
mkdir -p docker/trackme/certs
openssl req -x509 -newkey rsa:2048 \
-keyout docker/trackme/certs/key.pem \
-out docker/trackme/certs/chain.pem \
-days 1 -nodes \
mkdir -p certs
openssl req -x509 -newkey rsa:4096 \
-keyout certs/key.pem \
-out certs/chain.pem \
-sha256 -days 365 -nodes \
-subj "/CN=localhost" \
-addext "subjectAltName=IP:127.0.0.1,DNS:localhost"
# Combine system CAs with test CA so Go trusts the self-signed cert
cat /etc/ssl/certs/ca-certificates.crt docker/trackme/certs/chain.pem \
> /tmp/combined-test-cas.crt
jq '.log_to_db = false | .mongo_url = "" | .device = ""' \
config.example.json > config.json
cat /etc/ssl/certs/ca-certificates.crt certs/chain.pem > /tmp/combined-test-cas.crt

- name: Build and start TrackMe
- name: Build and start tlsfingerprint.com server
working-directory: .tlsfingerprint-server
run: |
docker compose -f docker-compose.test.yml up -d --build
echo "Waiting for TrackMe to become ready..."
if ! timeout 90 bash -c 'until docker inspect --format "{{.State.Health.Status}}" cycletls_python-trackme-1 2>/dev/null | grep -q healthy; do sleep 2; done'; then
echo "TrackMe did not become ready in time. Container logs:"
docker logs cycletls_python-trackme-1
docker compose up -d --build
echo "Waiting for tlsfingerprint.com server to become ready..."
if ! timeout 90 bash -c 'until curl -sk --max-time 3 https://localhost/api/clean -o /dev/null; do sleep 2; done'; then
echo "Server did not become ready in time. Container logs:"
docker compose logs
exit 1
fi
echo "TrackMe is ready."
echo "tlsfingerprint.com server is ready."

- name: Run blocking tests
env:
TRACKME_URL: https://localhost:8443
TLSFP_URL: https://localhost
SSL_CERT_FILE: /tmp/combined-test-cas.crt
run: uv run pytest -v --color=yes -m "blocking" tests/

- name: Tear down tlsfingerprint.com server
if: always()
working-directory: .tlsfingerprint-server
run: docker compose down -v || true
51 changes: 34 additions & 17 deletions .github/workflows/live-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,49 @@ jobs:
- name: Install dependencies
run: uv sync --locked --all-extras --dev

- name: Generate TLS certificates for TrackMe
- name: Checkout Danny-Dasilva/tlsfingerprint.com
uses: actions/checkout@v4
with:
repository: Danny-Dasilva/tlsfingerprint.com
ref: master
path: .tlsfingerprint-server

- name: Generate TLS certificates and config
working-directory: .tlsfingerprint-server
run: |
mkdir -p docker/trackme/certs
openssl req -x509 -newkey rsa:2048 \
-keyout docker/trackme/certs/key.pem \
-out docker/trackme/certs/chain.pem \
-days 1 -nodes \
mkdir -p certs
openssl req -x509 -newkey rsa:4096 \
-keyout certs/key.pem \
-out certs/chain.pem \
-sha256 -days 365 -nodes \
-subj "/CN=localhost" \
-addext "subjectAltName=IP:127.0.0.1,DNS:localhost"
# Combine system CAs with test CA so Go trusts the self-signed cert
cat /etc/ssl/certs/ca-certificates.crt docker/trackme/certs/chain.pem \
> /tmp/combined-test-cas.crt
# Disable mongo logging and clear mongo_url so the server doesn't try to connect to a DB.
jq '.log_to_db = false | .mongo_url = "" | .device = ""' \
config.example.json > config.json
# Combine system CAs with the test CA so the Go transport (and any tooling)
# trusts our self-signed cert via SSL_CERT_FILE.
cat /etc/ssl/certs/ca-certificates.crt certs/chain.pem > /tmp/combined-test-cas.crt

- name: Build and start TrackMe
- name: Build and start tlsfingerprint.com server
working-directory: .tlsfingerprint-server
run: |
docker compose -f docker-compose.test.yml up -d --build
echo "Waiting for TrackMe to become ready..."
if ! timeout 90 bash -c 'until docker inspect --format "{{.State.Health.Status}}" cycletls_python-trackme-1 2>/dev/null | grep -q healthy; do sleep 2; done'; then
echo "TrackMe did not become ready in time. Container logs:"
docker logs cycletls_python-trackme-1
docker compose up -d --build
echo "Waiting for tlsfingerprint.com server to become ready..."
if ! timeout 90 bash -c 'until curl -sk --max-time 3 https://localhost/api/clean -o /dev/null; do sleep 2; done'; then
echo "Server did not become ready in time. Container logs:"
docker compose logs
exit 1
fi
echo "TrackMe is ready."
echo "tlsfingerprint.com server is ready."

- name: Run live tests
env:
TRACKME_URL: https://localhost:8443
TLSFP_URL: https://localhost
SSL_CERT_FILE: /tmp/combined-test-cas.crt
run: uv run pytest -v --color=yes --reruns=3 -m "live and not blocking" tests/

- name: Tear down tlsfingerprint.com server
if: always()
working-directory: .tlsfingerprint-server
run: docker compose down -v || true
13 changes: 13 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
# macOS runners are scarce on free tier; only run macOS for the latest
# Python version. Linux covers the full Python matrix.
exclude:
- os: macos-latest
python: '3.9'
- os: macos-latest
python: '3.10'
- os: macos-latest
python: '3.11'
- os: macos-latest
python: '3.12'
- os: macos-latest
python: '3.14'

steps:
- uses: actions/checkout@v6
Expand Down
7 changes: 2 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,5 @@ site/
# Continuous Claude cache (local only)
.claude/cache/

# Generated test certificates for local TrackMe instance
docker/trackme/certs/

# Generated browser fingerprint captures
tests/integration/artifacts/*.json
# Local checkout of Danny-Dasilva/tlsfingerprint.com used by live-tests workflow
.tlsfingerprint-server/
17 changes: 8 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- Python 3.9 support (`requires-python = ">=3.9"`)
- `schema.py`: replaced `@dataclass(slots=True)` (Python 3.10+) with a
version-conditional equivalent; slots are still used on Python 3.10+
- `_batcher.py`: removed `zip(..., strict=True)` (Python 3.10+); the
length mismatch is already guarded by an explicit check above the loop
- Dev dependencies: added Python-version-conditional variants for
`pytest` and `pytest-asyncio` so the lock file resolves on Python 3.9
- CI: added Python 3.9 to the unit-test and live-test matrices
- `local_address` parameter to bind outgoing TCP connections to a specific local IP for outbound interface/IP selection (#65)

### Fixed
- `Do()` dropped `ServerName`, `TLS13AutoRetry`, and `DisableGrease` request fields when constructing the underlying request (#65)
- `TLS13AutoRetry` proactive upgrade corrupted JA3 `supported_groups`; the original JA3 ordering is now preserved across the retry (#65)
- `dispatchSSEAsync` could enter an infinite loop on stream cancel/EOF (#65)
24 changes: 12 additions & 12 deletions benchmarks/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.26

require (
github.com/Danny-Dasilva/CycleTLS/cycletls v1.0.30
github.com/valyala/fasthttp v1.70.0
github.com/valyala/fasthttp v1.71.0
)

require (
Expand All @@ -16,22 +16,22 @@ require (
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/klauspost/compress v1.18.5 // indirect
github.com/klauspost/compress v1.18.6 // indirect
github.com/onsi/ginkgo/v2 v2.23.4 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.57.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.53.0 // indirect
github.com/refraction-networking/uquic v0.0.6 // indirect
github.com/refraction-networking/utls v1.8.2 // indirect
github.com/refraction-networking/utls v1.8.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/mock v0.5.2 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 // indirect
golang.org/x/mod v0.33.0 // indirect
golang.org/x/net v0.51.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.35.0 // indirect
golang.org/x/tools v0.42.0 // indirect
golang.org/x/mod v0.32.0 // indirect
golang.org/x/net v0.50.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
golang.org/x/tools v0.41.0 // indirect
h12.io/socks v1.0.3 // indirect
)
Loading
Loading