Revert "fix: allow HTTP LNURL for RFC1918/loopback baseurls (#2)"
Some checks failed
lint.yml / Revert "fix: allow HTTP LNURL for RFC1918/loopback baseurls (#2)" (push) Failing after 0s
Some checks failed
lint.yml / Revert "fix: allow HTTP LNURL for RFC1918/loopback baseurls (#2)" (push) Failing after 0s
This reverts commit66026ab. Closes #2 as resolved by switching the dev LNbits to TLS (self-signed cert) instead of carving out plain HTTP for RFC1918 hosts. With HTTPS the producer-side python-lnurl validation accepts any host, AND the lnbits-core consumer-side `lnurlscan` accepts it too — the symmetric problem the carve-out couldn't solve on its own. `create_lnurl_from_baseurl` (#1, `e9d911e`) is kept — it's orthogonal to the transport scheme and still wanted for the nostr-transport `lnurl=null` fix.
This commit is contained in:
parent
0e06ab2087
commit
2877cf6b20
3 changed files with 5 additions and 107 deletions
41
helpers.py
41
helpers.py
|
|
@ -1,11 +1,7 @@
|
|||
import ipaddress
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from fastapi import Request
|
||||
from lnbits.settings import settings
|
||||
from lnurl import Lnurl
|
||||
from lnurl import encode as lnurl_encode
|
||||
from lnurl.helpers import url_encode
|
||||
from shortuuid import uuid
|
||||
|
||||
from .models import WithdrawLink
|
||||
|
|
@ -33,41 +29,12 @@ def create_lnurl(link: WithdrawLink, req: Request) -> Lnurl:
|
|||
) from e
|
||||
|
||||
|
||||
def _is_private_network_http(url: str) -> bool:
|
||||
"""True iff `url` is `http://` AND the host is loopback, `localhost`,
|
||||
or in an RFC1918 private range. These are intrinsically unreachable
|
||||
from the public internet, so producing an HTTP LNURL pointing at one
|
||||
is a dev/internal-test scenario, not a production misconfig.
|
||||
|
||||
Extends python-lnurl's existing `localhost` / `127.0.0.1` carve-out
|
||||
(see `lnurl.types.INSECURE_HOSTS`) to the full RFC1918 set so
|
||||
cross-device regtest smoke against a LAN-IP LNbits works without
|
||||
standing up TLS termination.
|
||||
"""
|
||||
parsed = urlparse(url)
|
||||
if parsed.scheme != "http":
|
||||
return False
|
||||
host = (parsed.hostname or "").lower()
|
||||
if host == "localhost":
|
||||
return True
|
||||
try:
|
||||
ip = ipaddress.ip_address(host)
|
||||
except ValueError:
|
||||
return False
|
||||
return ip.is_loopback or ip.is_private
|
||||
|
||||
|
||||
def create_lnurl_from_baseurl(link: WithdrawLink) -> tuple[str, str]:
|
||||
def create_lnurl_from_baseurl(link: WithdrawLink) -> Lnurl:
|
||||
"""
|
||||
Same shape as `create_lnurl`, but composes the callback URL from
|
||||
`settings.lnbits_baseurl` instead of a FastAPI `Request`. Used by
|
||||
the nostr-transport RPC handlers, which have no HTTP request to
|
||||
derive a base URL from.
|
||||
|
||||
Returns `(bech32, url)` — the two fields `_populate_lnurl` writes
|
||||
onto `WithdrawLink.lnurl` / `lnurl_url`. LAN-local HTTP URLs
|
||||
(loopback / RFC1918) skip python-lnurl's HTTPS-required check via
|
||||
the public `lnurl.helpers.url_encode` helper; see #2.
|
||||
"""
|
||||
base = settings.lnbits_baseurl.rstrip("/")
|
||||
if link.is_unique:
|
||||
|
|
@ -78,14 +45,10 @@ def create_lnurl_from_baseurl(link: WithdrawLink) -> tuple[str, str]:
|
|||
else:
|
||||
url = f"{base}/withdraw/api/v1/lnurl/{link.unique_hash}"
|
||||
|
||||
if _is_private_network_http(url):
|
||||
return url_encode(url), url
|
||||
|
||||
try:
|
||||
encoded = lnurl_encode(url)
|
||||
return lnurl_encode(url)
|
||||
except Exception as e:
|
||||
raise ValueError(
|
||||
f"Error creating LNURL with url: `{url!s}`, "
|
||||
"check your `LNBITS_BASEURL` configuration."
|
||||
) from e
|
||||
return str(encoded.bech32), str(encoded.url)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue