Adds security tools, such as a rate limiter, IP block/allow, server logs (#1606)

* added ratelimiter
* Adds server logs to admin ui
* Added IP allow/ban list
* fixed remove ips
* Split rate limit number and unit
* security tab and background tasks for killswitch
* fix test for auditor api

---------

Co-authored-by: dni  <office@dnilabs.com>
This commit is contained in:
Arc
2023-06-20 11:26:33 +02:00
committed by GitHub
co-authored by dni ⚡
parent 758a4ecaf6
commit 7e1f43933d
21 changed files with 963 additions and 123 deletions
+84 -2
View File
@@ -1,20 +1,102 @@
import asyncio
from typing import Dict
from typing import Dict, Optional
import httpx
from loguru import logger
from lnbits.settings import get_wallet_class, settings
from lnbits.tasks import SseListenersDict, register_invoice_listener
from . import db
from .crud import get_balance_notify, get_wallet
from .models import Payment
from .services import websocketUpdater
from .services import get_balance_delta, switch_to_voidwallet, websocketUpdater
api_invoice_listeners: Dict[str, asyncio.Queue] = SseListenersDict(
"api_invoice_listeners"
)
killswitch: Optional[asyncio.Task] = None
watchdog: Optional[asyncio.Task] = None
async def register_killswitch():
"""
Registers a killswitch which will check lnbits-status repository
for a signal from LNbits and will switch to VoidWallet if the killswitch is triggered.
"""
logger.debug("Starting killswitch task")
global killswitch
killswitch = asyncio.create_task(killswitch_task())
async def unregister_killswitch():
"""
Unregisters a killswitch taskl
"""
global killswitch
if killswitch:
logger.debug("Stopping killswitch task")
killswitch.cancel()
async def killswitch_task():
while True:
WALLET = get_wallet_class()
if settings.lnbits_killswitch and WALLET.__class__.__name__ != "VoidWallet":
with httpx.Client() as client:
try:
r = client.get(settings.lnbits_status_manifest, timeout=4)
r.raise_for_status()
if r.status_code == 200:
ks = r.json().get("killswitch")
if ks and ks == 1:
logger.error(
"Switching to VoidWallet. Killswitch triggered."
)
await switch_to_voidwallet()
except (httpx.ConnectError, httpx.RequestError):
logger.error(
f"Cannot fetch lnbits status manifest. {settings.lnbits_status_manifest}"
)
await asyncio.sleep(settings.lnbits_killswitch_interval * 60)
async def register_watchdog():
"""
Registers a watchdog which will check lnbits balance and nodebalance
and will switch to VoidWallet if the watchdog delta is reached.
"""
# TODO: implement watchdog porperly
# logger.debug("Starting watchdog task")
# global watchdog
# watchdog = asyncio.create_task(watchdog_task())
async def unregister_watchdog():
"""
Unregisters a watchdog task
"""
global watchdog
if watchdog:
logger.debug("Stopping watchdog task")
watchdog.cancel()
async def watchdog_task():
while True:
WALLET = get_wallet_class()
if settings.lnbits_watchdog and WALLET.__class__.__name__ != "VoidWallet":
try:
delta, *_ = await get_balance_delta()
logger.debug(f"Running watchdog task. current delta: {delta}")
if delta + settings.lnbits_watchdog_delta <= 0:
logger.error(f"Switching to VoidWallet. current delta: {delta}")
await switch_to_voidwallet()
except Exception as e:
logger.error("Error in watchdog task", e)
await asyncio.sleep(settings.lnbits_watchdog_interval * 60)
async def register_task_listeners():
"""