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:
+84
-2
@@ -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():
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user