Skip to content

Commit

Permalink
feat: Handle all 404 endpoints with RateLimit404 to mitigate DoS
Browse files Browse the repository at this point in the history
- Added RateLimit404 class to restrict repeated 404 requests, reducing potential DoS vectors.
- Enhanced error logging in process_webhook to capture full exception info.
- Improved request cleanup in RateLimit404 to prevent memory overflow.
- Updated server startup error handling to provide clearer diagnostics.
  • Loading branch information
orenlab committed Nov 1, 2024
1 parent cd20cf2 commit 81a4453
Showing 1 changed file with 57 additions and 21 deletions.
78 changes: 57 additions & 21 deletions pytmbot/webhook.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,81 @@
import telebot
from fastapi import FastAPI, HTTPException
from telebot import TeleBot

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from pytmbot.globals import settings
from pytmbot.logs import bot_logger
from time import time
import uvicorn


class WebhookServer:
class RateLimit404:
def __init__(self, limit: int, period: int):
"""
Initializes the rate limiter for 404 requests.
"""
self.limit = limit
self.period = period
self.requests = {}

def is_rate_limited(self, client_ip: str) -> bool:
"""
Checks if a client IP exceeds the rate limit for 404 errors.
"""
current_time = time()
request_times = self.requests.setdefault(client_ip, [])

self.requests[client_ip] = [
t for t in request_times if t > current_time - self.period
]

if len(self.requests[client_ip]) >= self.limit:
return True

self.requests[client_ip].append(current_time)
return False


class WebhookServer:
def __init__(self, bot: TeleBot, token: str, host: str, port: int):
"""
Initializes the FastAPI webhook server.
Args:
bot (TeleBot): The instance of the Telegram bot.
token (str): The Telegram bot token.
host (str): The host for the server.
port (int): The port for the server.
"""
self.bot = bot
self.token = token
self.app = FastAPI(docs=None, redoc_url=None, title="PyTMBot Webhook Server", version="0.1.0")
self.host = host
self.port = port
self.app = FastAPI(
docs=None, redoc_url=None, title="PyTMBot Webhook Server", version="0.1.0"
)
self.rate_limiter = RateLimit404(limit=8, period=10)

@self.app.exception_handler(404)
def not_found_handler(request: Request, exc: HTTPException):
client_ip = request.client.host
if self.rate_limiter.is_rate_limited(client_ip):
return JSONResponse(
status_code=429, content={"detail": "Rate limit exceeded"}
)
return JSONResponse(
status_code=404,
content={"detail": "Endpoint not found or method not allowed"},
)

@self.app.post(f"/webhook/{self.token}/")
def process_webhook(update: dict):
"""
Process webhook calls
Process webhook calls.
"""
try:
if update:
bot_logger.debug(f"Received webhook update: {update}")
update = telebot.types.Update.de_json(update)
self.bot.process_new_updates([update])
else:
if not update:
bot_logger.warning("No update found in the request.")
raise HTTPException(status_code=400, detail="Bad Request")

bot_logger.debug(f"Received webhook update: {update}")
update = telebot.types.Update.de_json(update)
self.bot.process_new_updates([update])
return {"status": "ok"}

except Exception as e:
bot_logger.error(f"Failed to process update: {e}")
raise HTTPException(status_code=500, detail="Internal Server Error")
Expand All @@ -47,11 +84,10 @@ def run(self):
"""
Starts the FastAPI application.
"""
import uvicorn

# Start the server with error handling
try:
bot_logger.info(f"Starting FastAPI webhook server on {self.host}:{self.port}...")
bot_logger.info(
f"Starting FastAPI webhook server on {self.host}:{self.port}..."
)

uvicorn.run(
self.app,
Expand All @@ -60,7 +96,7 @@ def run(self):
ssl_certfile=settings.webhook_config.cert[0].get_secret_value(),
ssl_keyfile=settings.webhook_config.cert_key[0].get_secret_value(),
log_level="critical",
use_colors=True
use_colors=True,
)
except Exception as e:
bot_logger.critical(f"Failed to start FastAPI server: {e}")
Expand Down

0 comments on commit 81a4453

Please sign in to comment.