diff --git a/src/pretix/base/email.py b/src/pretix/base/email.py
index db3ee6299a..dc0a59915d 100644
--- a/src/pretix/base/email.py
+++ b/src/pretix/base/email.py
@@ -19,7 +19,6 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# .
#
-import ipaddress
import logging
import smtplib
import socket
@@ -52,13 +51,12 @@ from pretix.base.services.placeholders import ( # noqa
SimpleFunctionalTextPlaceholder as SimpleFunctionalMailTextPlaceholder,
)
from pretix.base.settings import get_name_parts_localized # noqa
+from pretix.helpers.ssrf import should_block_access
logger = logging.getLogger('pretix.base.email')
T = TypeVar("T", bound=EmailBackend)
-_cgnat_net = ipaddress.ip_network('100.64.0.0/10')
-
def test_custom_smtp_backend(backend: T, from_addr: str) -> None:
try:
@@ -254,16 +252,9 @@ def create_connection(address, timeout=socket.getdefaulttimeout(),
af, socktype, proto, canonname, sa = res
if not getattr(settings, "MAIL_CUSTOM_SMTP_ALLOW_PRIVATE_NETWORKS", False):
- ip_addr = ipaddress.ip_address(sa[0])
- check_ip4 = ip_addr.ipv4_mapped if getattr(ip_addr, "ipv4_mapped", None) else ip_addr
- if ip_addr.is_multicast:
- raise socket.error(f"Request to multicast address {sa[0]} blocked")
- if ip_addr.is_loopback or ip_addr.is_link_local:
- raise socket.error(f"Request to local address {sa[0]} blocked")
- if ip_addr.is_private:
- raise socket.error(f"Request to private address {sa[0]} blocked")
- if check_ip4 in _cgnat_net:
- raise socket.error(f"Request to RFC 6598 address {sa[0]} blocked")
+ is_private, msg = should_block_access(sa)
+ if is_private:
+ raise socket.error(msg)
sock = None
try:
diff --git a/src/pretix/helpers/monkeypatching.py b/src/pretix/helpers/monkeypatching.py
index 39150e3341..a92b3785b0 100644
--- a/src/pretix/helpers/monkeypatching.py
+++ b/src/pretix/helpers/monkeypatching.py
@@ -19,7 +19,6 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# .
#
-import ipaddress
import socket
import sys
import types
@@ -42,8 +41,7 @@ from urllib3.util.connection import (
from urllib3.util.timeout import _DEFAULT_TIMEOUT
from pretix.helpers.reportlab import ThumbnailingImageReader
-
-_cgnat_net = ipaddress.ip_network('100.64.0.0/10')
+from pretix.helpers.ssrf import should_block_access
def monkeypatch_vobject_performance():
@@ -150,16 +148,9 @@ def monkeypatch_urllib3_ssrf_protection():
af, socktype, proto, canonname, sa = res
if not getattr(settings, "ALLOW_HTTP_TO_PRIVATE_NETWORKS", False):
- ip_addr = ipaddress.ip_address(sa[0])
- check_ip4 = ip_addr.ipv4_mapped if getattr(ip_addr, "ipv4_mapped", None) else ip_addr
- if ip_addr.is_multicast:
- raise HTTPError(f"Request to multicast address {sa[0]} blocked")
- if ip_addr.is_loopback or ip_addr.is_link_local:
- raise HTTPError(f"Request to local address {sa[0]} blocked")
- if ip_addr.is_private:
- raise HTTPError(f"Request to private address {sa[0]} blocked")
- if check_ip4 in _cgnat_net:
- raise HTTPError(f"Request to RFC 6598 address {sa[0]} blocked")
+ is_private, msg = should_block_access(sa)
+ if is_private:
+ raise HTTPError(msg)
sock = None
try:
diff --git a/src/pretix/helpers/ssrf.py b/src/pretix/helpers/ssrf.py
new file mode 100644
index 0000000000..03598ee4a9
--- /dev/null
+++ b/src/pretix/helpers/ssrf.py
@@ -0,0 +1,19 @@
+import ipaddress
+
+
+_cgnat_net = ipaddress.ip_network('100.64.0.0/10')
+
+
+def should_block_access(sa):
+ ip_addr = ipaddress.ip_address(sa[0])
+ check_ip4 = ip_addr.ipv4_mapped if getattr(ip_addr, "ipv4_mapped", None) else ip_addr
+ if ip_addr.is_multicast:
+ return True, f"Request to multicast address {sa[0]} blocked"
+ if ip_addr.is_loopback or ip_addr.is_link_local:
+ return True, f"Request to local address {sa[0]} blocked"
+ if ip_addr.is_private:
+ return True, f"Request to private address {sa[0]} blocked"
+ if check_ip4 in _cgnat_net:
+ return True, f"Request to RFC 6598 address {sa[0]} blocked"
+
+ return False, None