Add SSH keepalive and TCP keepalive to prevent silent disconnects
All checks were successful
Build ts3query-proxy / build (push) Successful in 35s
All checks were successful
Build ts3query-proxy / build (push) Successful in 35s
- SSH keepalive every 30s (configurable via SSH_KEEPALIVE_INTERVAL) - TCP keepalive on client sockets - Increase pre-auth timeout from 30s to 300s - Log keepalive settings on startup
This commit is contained in:
parent
8894916d03
commit
0bf4bf15e9
1 changed files with 15 additions and 3 deletions
18
proxy.py
18
proxy.py
|
|
@ -17,6 +17,10 @@ TS6_SSH_PORT = int(os.environ.get("TS6_SSH_PORT", "10022"))
|
|||
LISTEN_HOST = "0.0.0.0"
|
||||
LISTEN_PORT = int(os.environ.get("LISTEN_PORT", "10011"))
|
||||
|
||||
# Keepalive settings
|
||||
SSH_KEEPALIVE_INTERVAL = int(os.environ.get("SSH_KEEPALIVE_INTERVAL", "30"))
|
||||
SSH_KEEPALIVE_COUNT_MAX = int(os.environ.get("SSH_KEEPALIVE_COUNT_MAX", "3"))
|
||||
|
||||
TS3_BANNER = (
|
||||
b"TS3\n\r"
|
||||
b"Welcome to the TeamSpeak 3 ServerQuery interface, "
|
||||
|
|
@ -36,6 +40,12 @@ class ClientHandler:
|
|||
async def handle(self) -> None:
|
||||
log.info("Client connected from %s", self.addr)
|
||||
try:
|
||||
# Enable TCP keepalive on the client socket
|
||||
sock = self.writer.get_extra_info("socket")
|
||||
if sock:
|
||||
import socket
|
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
|
||||
|
||||
self.writer.write(TS3_BANNER)
|
||||
await self.writer.drain()
|
||||
await self._auth_loop()
|
||||
|
|
@ -50,7 +60,7 @@ class ClientHandler:
|
|||
|
||||
async def _auth_loop(self) -> None:
|
||||
while True:
|
||||
line = await asyncio.wait_for(self.reader.readline(), timeout=30)
|
||||
line = await asyncio.wait_for(self.reader.readline(), timeout=300)
|
||||
if not line:
|
||||
return
|
||||
cmd = line.decode("utf-8", errors="replace").strip()
|
||||
|
|
@ -98,6 +108,8 @@ class ClientHandler:
|
|||
username=username,
|
||||
password=password,
|
||||
known_hosts=None,
|
||||
keepalive_interval=SSH_KEEPALIVE_INTERVAL,
|
||||
keepalive_count_max=SSH_KEEPALIVE_COUNT_MAX,
|
||||
),
|
||||
timeout=10,
|
||||
)
|
||||
|
|
@ -118,7 +130,7 @@ class ClientHandler:
|
|||
except asyncio.TimeoutError:
|
||||
break
|
||||
|
||||
log.info("SSH session established for %s", self.addr)
|
||||
log.info("SSH session established for %s (keepalive=%ds)", self.addr, SSH_KEEPALIVE_INTERVAL)
|
||||
return True
|
||||
except asyncssh.PermissionDenied:
|
||||
log.warning("SSH auth failed for %s (bad credentials)", self.addr)
|
||||
|
|
@ -161,7 +173,6 @@ class ClientHandler:
|
|||
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
||||
for t in pending:
|
||||
t.cancel()
|
||||
# Await cancelled tasks to suppress warnings
|
||||
for t in pending:
|
||||
try:
|
||||
await t
|
||||
|
|
@ -201,6 +212,7 @@ async def main() -> None:
|
|||
server = await asyncio.start_server(handle_client, LISTEN_HOST, LISTEN_PORT)
|
||||
log.info("TS3 Query Proxy listening on %s:%d", LISTEN_HOST, LISTEN_PORT)
|
||||
log.info("Forwarding to %s:%d (SSH Query)", TS6_HOST, TS6_SSH_PORT)
|
||||
log.info("SSH keepalive: interval=%ds, max_count=%d", SSH_KEEPALIVE_INTERVAL, SSH_KEEPALIVE_COUNT_MAX)
|
||||
async with server:
|
||||
await server.serve_forever()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue