From b84f2e8c993613d657ac6866be29de2c5dea5bb2 Mon Sep 17 00:00:00 2001 From: bitdeals Date: Wed, 19 Aug 2026 08:35:59 +0000 Subject: [PATCH] docs: show the log, and that it holds no addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Notes explain at length that no visitor's IP address reaches the log and why both loggers are hand-written to keep it that way. Nothing showed it. A reader had to take the claim on faith or read haproxy.cfg. Add a "the log" section to Usage in both READMEs: a real `docker compose logs haproxy` excerpt from a running node, the two log formats broken down field by field, and the point the sample exists to make — the first field is the X-Client-Id pseudonym, and it is all the log knows about who connected. --- README.md | 35 +++++++++++++++++++++++++++++++++++ README.ru-RU.md | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/README.md b/README.md index 2bf4c27..d7beff0 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,41 @@ docker run --rm -v "$PWD/docker/haproxy.cfg:/tmp/haproxy.cfg:ro" \ registry.bitdeals.org/haproxy -c -f /tmp/haproxy.cfg ``` +## the log + +`docker compose logs haproxy` on a running node: + +```text +haproxy-1 | XFF_HMAC_KEY was not set — generated one for this container. +haproxy-1 | [NOTICE] (1) : Automatically setting global.maxconn to 32745. +haproxy-1 | rlj13BvDLpJLzzHbutTiC5fjK0OR4YRlPrYnJIHpO7Y= [18/Aug/2026:10:25:25.196] http 1/1 Success +haproxy-1 | wgM6JB1uN2AGFKkl67+O7SCx+DHrGttufQw0HDQMSIU= [18/Aug/2026:10:45:10.700] https~ 1/1 SSL handshake failure +haproxy-1 | 5056er7Wogz59zFJfaNNelKpEnxzEISztzbgn/omnHg= [18/Aug/2026:10:54:38.337] https~ 1/1 Connection closed during SSL handshake +haproxy-1 | 6TPbf9FXhRxBoy+SSpFrOuTvYjZF3RjTQmdCteZWH3s= [19/Aug/2026:04:13:17.521] https~ default-backend-http/main 400 289 0/497 SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ +``` + +**No line carries an IP address, and none can.** The first field is the +pseudonym from `X-Client-Id` — HMAC-SHA256 of the visitor's address under +`XFF_HMAC_KEY`, base64 — and it is everything the log knows about who +connected. Both loggers are written out by hand for exactly that reason: their +defaults open with `%ci:%cp`, the address and the port. See Notes. + +The four request lines are the two formats: + +- connection level, `%[var(sess.cid)] [%tr] %ft %ac/%fc %[fc_err_str]` — + pseudonym, time, frontend, connection counts, how the connection ended. + Everything that dies before a request exists lands here: a client that offers + nothing above TLS 1.1, a scanner that hangs up mid-handshake, a probe that + opened the port and left. +- transaction level, `… %ft %b/%s %ST %B %TR/%Ta %HM %HP` — pseudonym, time, + frontend, backend/server, status, bytes, timers, method, path. The last line + is a 400 for a stray SSTP probe. The path ends where the query string starts; + that part is never logged. + +Successful requests write nothing at all (`option dontlog-normal`), so a log +this quiet is the normal state of a working node, not a sign that the loggers +are misconfigured. + ## build and publish A push to `main` builds and publishes the image diff --git a/README.ru-RU.md b/README.ru-RU.md index bd3f7c9..4140fd2 100644 --- a/README.ru-RU.md +++ b/README.ru-RU.md @@ -75,6 +75,41 @@ docker run --rm -v "$PWD/docker/haproxy.cfg:/tmp/haproxy.cfg:ro" \ registry.bitdeals.org/haproxy -c -f /tmp/haproxy.cfg ``` +## Журнал + +`docker compose logs haproxy` на работающем узле: + +```text +haproxy-1 | XFF_HMAC_KEY was not set — generated one for this container. +haproxy-1 | [NOTICE] (1) : Automatically setting global.maxconn to 32745. +haproxy-1 | rlj13BvDLpJLzzHbutTiC5fjK0OR4YRlPrYnJIHpO7Y= [18/Aug/2026:10:25:25.196] http 1/1 Success +haproxy-1 | wgM6JB1uN2AGFKkl67+O7SCx+DHrGttufQw0HDQMSIU= [18/Aug/2026:10:45:10.700] https~ 1/1 SSL handshake failure +haproxy-1 | 5056er7Wogz59zFJfaNNelKpEnxzEISztzbgn/omnHg= [18/Aug/2026:10:54:38.337] https~ 1/1 Connection closed during SSL handshake +haproxy-1 | 6TPbf9FXhRxBoy+SSpFrOuTvYjZF3RjTQmdCteZWH3s= [19/Aug/2026:04:13:17.521] https~ default-backend-http/main 400 289 0/497 SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ +``` + +**Ни в одной строке нет IP-адреса, и появиться ему неоткуда.** Первое поле — +псевдоним из `X-Client-Id`, HMAC-SHA256 от адреса посетителя на ключе +`XFF_HMAC_KEY` в base64, — и это всё, что журнал знает о том, кто подключился. +Оба логгера выписаны вручную именно поэтому: их умолчания начинаются с +`%ci:%cp`, то есть с адреса и порта. См. «Замечания». + +Четыре строки обращений — это два формата: + +- уровень соединения, `%[var(sess.cid)] [%tr] %ft %ac/%fc %[fc_err_str]`: + псевдоним, время, фронтенд, счётчики соединений, чем соединение кончилось. + Сюда попадает всё, что умирает до появления запроса: клиент, не предлагающий + ничего выше TLS 1.1, сканер, обрывающий рукопожатие на середине, проба, + которая открыла порт и ушла. +- уровень транзакции, `… %ft %b/%s %ST %B %TR/%Ta %HM %HP`: псевдоним, время, + фронтенд, бэкенд/сервер, статус, байты, таймеры, метод, путь. Последняя строка + — 400 в ответ на случайную SSTP-пробу. Путь заканчивается там, где начинается + строка запроса: её в журнале нет никогда. + +Успешные запросы не пишутся вовсе (`option dontlog-normal`), поэтому настолько +тихий журнал — нормальное состояние работающего узла, а не признак того, что +логгеры настроены неверно. + ## Сборка и публикация Push в `main` собирает и публикует образ (`.gitea/workflows/build.yaml`) с тремя