fix(proxy): flush disconnect packet cleanly + label handshake errors
Two related diagnostics from production: 1) "Connection reset" instead of the custom block_message screen. Root cause: writer.close() returned before the kernel flushed the Login Disconnect packet, and the OS sent RST instead of FIN. Fix: write_eof() + await wait_closed() so the FIN goes out after the payload and the client has time to read the chat component. 2) Log entries showing reason "handshake error:" with an empty tail. Root cause: bare OSError() / ConnectionResetError() have empty str(), so the f-string interpolated to nothing. Fix: prepend the exception class name so the reason is always informative.
This commit is contained in:
@@ -228,9 +228,16 @@ async def handle_client(
|
||||
)
|
||||
hs = parse_handshake(hs_bytes)
|
||||
except (HandshakeError, asyncio.TimeoutError, asyncio.IncompleteReadError, OSError) as exc:
|
||||
log_event(client_ip, None, None, "blocked", f"handshake error: {exc}")
|
||||
log.info("BLOCK %s reason=handshake_error (%s)", client_ip, exc)
|
||||
# str(exc) 가 빈 문자열인 예외들(OSError(), ConnectionResetError())
|
||||
# 도 있어서 class 이름을 함께 남긴다 — 빈 reason 로 보이는 문제 회피.
|
||||
reason = f"handshake error: {type(exc).__name__}: {exc}".rstrip(": ")
|
||||
log_event(client_ip, None, None, "blocked", reason)
|
||||
log.info("BLOCK %s reason=%s", client_ip, reason)
|
||||
try:
|
||||
client_writer.close()
|
||||
await client_writer.wait_closed()
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
return
|
||||
|
||||
domain = hs.server_address.lower().strip()
|
||||
@@ -247,9 +254,20 @@ async def handle_client(
|
||||
msg = state.cfg.get("block_message") or DEFAULT_BLOCK_MESSAGE
|
||||
client_writer.write(build_login_disconnect(msg))
|
||||
await client_writer.drain()
|
||||
# FIN 으로 마무리해서 클라이언트가 disconnect 패킷을 다 읽기 전에
|
||||
# RST 가 가는 (그러면 "Connection reset" 으로 보인다) 일을 막는다.
|
||||
try:
|
||||
if client_writer.can_write_eof():
|
||||
client_writer.write_eof()
|
||||
except (OSError, NotImplementedError):
|
||||
pass
|
||||
except (OSError, ConnectionResetError, BrokenPipeError):
|
||||
pass
|
||||
try:
|
||||
client_writer.close()
|
||||
await client_writer.wait_closed()
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
return
|
||||
|
||||
backend_host, backend_port = target
|
||||
|
||||
Reference in New Issue
Block a user