Caddy + Forward_Proxy (NaiveProxy): Auth success (200 OK), but zero traffic (Content-Length: 0)

Hello everyone! I need some help debugging my NaiveProxy setup. I’ve been struggling with this for two weeks now. I’ve tried everything (Windows, Kali, mobile and home ISPs, different VPS providers), but the tunnel just won’t work.

My Stack:

  • Server: Debian/Ubuntu, Caddy v2 built via xcaddy with the forward_proxy module.

  • Client: NaiveProxy (latest builds on Kali and Windows).

  • Domain: Personal domain with valid Let’s Encrypt SSL. Cloudflare is NOT used (DNS-only/Direct IP).

The Problem: When attempting to use the proxy, authentication is successful (I see 200 OK or 407 in the logs), but the response from the target resource is always empty (Content-Length: 0). The connection either hangs or is dropped immediately.

What I’ve already tried:

  • HTTP/2 Verification: The server confirms H2 support. curl -I --http2 returns 407 Proxy Authentication Required. However, when actually using the proxy, curl often falls back to HTTP/1.1.

  • Caddy Configuration:

    • Wrapped directives in a route { ... } block for strict ordering.

    • Used order forward_proxy before file_server in global options.

    • Toggled probe_resistance on and off.

  • Network Settings:

    • Adjusted MTU (down to 1300) — no effect.

    • Tested on different ports (443, 8443).

    • Firewall (ufw/iptables) is configured correctly.

  • Client-side:

    • Tested on multiple OS (Windows 11, Kali Linux).

    • Tried forcing --http2-prior-knowledge in curl.

  • Caddy Logs (Debug): In debug mode, I see the client request and a successful tls.handshake. However, it’s followed by: handled request ... status: 200 with zero size.

Symptoms: It feels like the HTTP/2 tunnel collapses immediately after the handshake, and Caddy fails to multiplex/forward traffic within the stream.

Any ideas? Could this be related to a specific build issue of the module or TLS libraries on the system? Any help is greatly appreciated!

Looks like an issue with software setup. Have you tried proxy engines, such as Xray / sing-box instead?

Firstly make something working, then shift to your setup slowly, you’ll see what breaks.

Because the first question is what doesn’t break.

Have you been following this guide?
Have you tried enabling debug in caddy config and reading the log? Nevermind.
Have you verified you can connect to Naive directly so we know it works?
The default Caddy configuration on Naive’s repo specifies basic_auth user pass, meaning authorization is enabled. Do you have user=user, password=pass specified in your proxy client’s config?

If nothing works, you can also try using nginx or haproxy.

Thanks for the suggestions! Here is a summary of what has been tested and verified so far:

  1. Direct Connection: The decoy site is displayed correctly. The TLS certificate is valid (Let’s Encrypt), and browsers don’t report any issues. Previously, when the directive order was wrong, the server correctly returned 407 Proxy Authentication Required, so the forward_proxy module is definitely active.

  2. Probe Resistance: I have tried commenting out the probe_resistance line entirely. Unfortunately, it didn’t help — the result is still an Auth Success (200 OK) but with Content-Length: 0 and zero traffic flow.

  3. Client Tests (curl): I’m testing with curl -v -x https:// user:pass @domain.comdomain.com. Even though the connection is established, the tunnel doesn’t seem to forward data inside the HTTP/2 stream.

  4. Modules: Confirmed forward_proxy is present in caddy list-modules. I’m using the standard basic_auth user pass syntax within the proxy block.

Question: Could this be an ALPN negotiation issue or something related to how Caddy handles the H2 stream if the client doesn’t strictly behave like a “Naive” client?

PS: прошу прощения что изначально написал на английском (температурил, глаз замылился с отладкой и так получилось…) дальше можно продолжать на русском или оставить этот топик как есть (на английском) - не знаю как лучше… Благодарю администрацию (@ValdikSS) что помогли с разблокировкой первой моей здесь темы…
PPS: сейчас всё удалил и сделал заново точно по гайду приведённому вами. Ошибка не ушала. Всё осталось как было. Сейчас попробую параллельно поставить в доккере. Исключу что что-то в Debian 12 мешает трафику…

В логах Naive что-то есть (логи нужно будет включить флагом перед тестом)?
Если нет, попробуйте постучаться на порт Naive напрямую в обход caddy и посмотреть, работает ли, чтобы исключить проблему с самим Naive (лучше это делать через другую прокси, чтобы в логах ISP не было подключений на нестандартные порты).

Я провёл тест “в три окна” как с обычным конфигом так и с упрощённым. В упрощённом варианте убрал из Caddyfile probe_resistance и пр. фильтры. Картина получается такая: 1) TLS Handshake проходит идеально, сертификат подхватывается 2) В логах Naive: negotiated padding type: None и сразу Connection closed: OK 3) В логах Caddy (debug): Полная тишина со стороны forward_proxy. После рукопожатия нет ни одной записи о попытке авторизации или проксирования. Запрос просто проваливается в file_server.
Иными словами как это вижу я. Клиент и сервер договариваются о формате данных. Клиент считает, что всё прошло успешно. Он получил от сервера ответ 200 OK и закрыл соединение. Но это был 200 OK от моей странички-заглушки, а не от прокси-туннеля. Т.е. После успешного TLS-рукопожатия Caddy вообще не передает запрос модулю forward_proxy. В логах нет ни слова про http.handlers.forward_proxy или authentication.
Тут бы я подумал в сторону версий плагина и параметров сборки бинарника, но я до этого пробовал разные вариант и версий Go и пр. А вчера вообще поставил Наив в Докере - идеальная среда и получил такую же картину…

Лог запуска клиента (./naive config.json)

[INFO:naive_proxy_bin.cc(217)] Proxying via HTTPS example.com:443 [INFO:naive_proxy_bin.cc(479)] Listening on socks://127.0.0.1:1090 [INFO:naive_connection.cc(277)] Connection 1 to www.google.com:443 [INFO:naive_proxy_delegate.cc(154)] https://example.com:443 negotiated padding type: None [INFO:naive_proxy.cc(185)] Connection 1 closed: OK

Результат запроса (curl)

  • Trying 127.0.0.1:1090…
  • Opened SOCKS connection from 127.0.0.1 to www.google.com port 443
  • ALPN: curl offers h2,http/1.1
  • TLSv1.3 (OUT), TLS handshake, Client hello (1):
  • TLSv1.3 (OUT), TLS alert, decode error (562):
  • TLS connect error: error:0A000126:SSL routines::unexpected eof while reading
  • closing connection #0
    curl: (35) TLS connect error: error:0A000126:SSL routines::unexpected eof while reading

Лог сервера (sudo journalctl -u caddy -f)

# Сразу после запуска curl на клиенте: Apr 24 23:49:26 server caddy[48209]: {“level”:“debug”,“ts”:1777074566.685068,“logger”:“events”,“msg”:“event”,“name”:“tls_get_certificate”,“id”:“[REDACTED_ID]”,“origin”:“tls”,“data”:{“client_hello”:{“CipherSuites”:[2570,4865,4866,4867,49195,49199,49196,49200,52393,52392,49171,49172,156,157,47,53],“ServerName”:“example.com”,“SupportedCurves”:[19018,25497,29,23,24],“SupportedPoints”:“AA==”,“SignatureSchemes”:[1027,2052,1025,1283,2053,1281,2054,1537],“SupportedProtos”:[“h2”,“http/1.1”],“SupportedVersions”:[60138,772,771],“RemoteAddr”:{“IP”:“USER_IP”,“Port”:54294,“Zone”:“”},“LocalAddr”:{“IP”:“SERVER_IP”,“Port”:443,“Zone”:“”}}}} Apr 24 23:49:26 server caddy[48209]: {“level”:“debug”,“ts”:1777074566.685154,“logger”:“tls.handshake”,“msg”:“choosing certificate”,“identifier”:“example.com”,“num_choices”:1} Apr 24 23:49:26 server caddy[48209]: {“level”:“debug”,“ts”:1777074566.6852086,“logger”:“tls.handshake”,“msg”:“default certificate selection results”,“identifier”:“example.com”,“subjects”:[“example.com”],“managed”:true,“issuer_key”:“acme-v02.api.letsencrypt.org-directory”,“hash”:“[REDACTED_HASH]”} Apr 24 23:49:26 server caddy[48209]: {“level”:“debug”,“ts”:1777074566.6852279,“logger”:“tls.handshake”,“msg”:“matched certificate in cache”,“remote_ip”:“USER_IP”,“remote_port”:“54294”,“subjects”:[“example.com”],“managed”:true,“expiration”:1784844316,“hash”:“[REDACTED_HASH]”}

После этой строки лог обрывается. Никаких упоминаний http.handlers.forward_proxy или попыток dialing нет.

{
debug
order forward_proxy before file_server
}

example.com, www.example.com {
tls user@example.com

forward_proxy {
    basic_auth login password

}

root * /var/www/html
file_server

}

С таким упрощённыи для теста конфигом ещё и сайт не открывается, тоесть видимо forward_proxy так мешает работе сервера…

Судя по логам, трафик действительно не доходит до naive.

Я бы попробовал исключить Caddy и посмотреть, работает ли с другим реверс прокси.

Префикс :443, обязателен, без него naive работать не будет. Без него forward_proxy цепляется не к листенеру на 443, а к виртуальному хосту, и CONNECT-запросы от naive просто не доходят до прокси-логики.

Ну и www разведи отдельным блоком на редирект, так чище. А основной блок пусть слушает именно :443, example.com - Caddy тогда вешает TLS-листенер на 443 для этого домена, и туннели naive внутри TLS-сессии нормально попадают в forward_proxy.

Большое спсибо!! Всё заработало. К своему стыду я когда действовал по гайду с гитхаба не сделал по новой файл конфига, а пробежался глазами по своему старому и не заметил “:443, your-domain.com” добавил это, разнёс блоки с www и без и заработало :slightly_smiling_face: Всем большое спасибо за советы!!