proxy support fixes

This commit is contained in:
Nils Büchner 2024-09-18 22:48:26 +02:00
parent 744c8d1b8b
commit e81f308792

View file

@ -1,4 +1,4 @@
import treq import requests
import json import json
import time import time
import os import os
@ -49,61 +49,45 @@ class InviteChecker:
self.api.register_spam_checker_callbacks(user_may_invite=self.user_may_invite) self.api.register_spam_checker_callbacks(user_may_invite=self.user_may_invite)
logger.info("InviteChecker initialized") logger.info("InviteChecker initialized")
@inlineCallbacks
def fetch_json(self, url): def fetch_json(self, url):
logger.info(f"Fetching JSON data from: {url}") logger.info(f"Fetching JSON data from: {url}")
# Fetch proxy from the environment variable # Read proxy configuration from the environment variable 'https_proxy', if set
https_proxy = os.getenv('https_proxy') https_proxy = os.getenv('https_proxy', None)
headers = None # Initialize headers to None proxies = {}
if https_proxy: if https_proxy:
logger.info(f"Using HTTPS proxy: {https_proxy}") # Mask credentials in the proxy URL
if '@' in https_proxy:
# Parse the proxy URL with optional username and password masked_proxy = '****:****@' + https_proxy.split('@')[1]
if '@' in https_proxy: # Check if authentication info is present
credentials, proxy_hostport = https_proxy.split('@')
username, password = credentials.split(':')
proxy_host, proxy_port = proxy_hostport.split(':')
# Create basic authentication header
auth_string = f'{username}:{password}'
auth_bytes = base64.b64encode(auth_string.encode('utf-8')).decode('utf-8')
headers = Headers({
'Proxy-Authorization': [f'Basic {auth_bytes}']
})
else: else:
headers = None masked_proxy = https_proxy
proxy_host, proxy_port = https_proxy.split(':')
proxy_endpoint = TCP4ClientEndpoint(reactor, proxy_host, int(proxy_port)) proxies = {
"https": https_proxy
# Create a ProxyAgent with authentication if needed }
agent = ProxyAgent(proxy_endpoint) logger.info(f"Using HTTPS proxy: {masked_proxy}")
else: else:
# If no proxy is set, use the default agent logger.info("No proxy configured, making direct request")
agent = Agent(reactor)
try: try:
# Pass headers to the request if authentication is required # Make the request with the proxy if set, otherwise direct
if headers: response = requests.get(url, proxies=proxies, timeout=10)
response = yield treq.get(url, agent=agent, headers=headers)
else:
response = yield treq.get(url, agent=agent)
if response.code == 200: # Log the response status code
content = yield response.content() logger.info(f"Received response with status code: {response.status_code}")
data = json.loads(content.decode('utf-8'))
# Check for a successful response
if response.status_code == 200:
data = response.json() # Parse the JSON data
logger.debug(f"Received JSON data: {data}") logger.debug(f"Received JSON data: {data}")
returnValue(data) return data
else: else:
logger.error(f"Failed to fetch JSON data. Status code: {response.code}") logger.error(f"Non-200 response code: {response.status_code}, Response body: {response.text}")
returnValue(None) return None
except Exception as e: except Exception as e:
logger.error(f"Error while fetching JSON: {str(e)}") logger.error(f"Error while fetching JSON: {str(e)} - {type(e).__name__}")
returnValue(None) return None
@inlineCallbacks @inlineCallbacks
def fetch_policy_room_banlist(self): def fetch_policy_room_banlist(self):
@ -153,17 +137,22 @@ class InviteChecker:
"""Fetch and update the blocklist, allowlist, and blocklisted room IDs.""" """Fetch and update the blocklist, allowlist, and blocklisted room IDs."""
logger.info("Updating blocklist, allowlist, and room blocklist") logger.info("Updating blocklist, allowlist, and room blocklist")
json_data = yield self.fetch_json(self.config.blocklist_allowlist_url) json_data = self.fetch_json(self.config.blocklist_allowlist_url)
if json_data: if json_data:
logger.debug(f"Fetched JSON data: {json_data}") # Log the full JSON data for verification
self.allow_all_invites_on_error = False self.allow_all_invites_on_error = False
self.use_allowlist = json_data.get('use_allowlist', True) self.use_allowlist = json_data.get('use_allowlist', True)
self.use_blocklist = json_data.get('use_blocklist', True) self.use_blocklist = json_data.get('use_blocklist', True)
self.blocklist = set(json_data.get('blocklist', [])) self.blocklist = set(json_data.get('blocklist', []))
self.allowlist = set(json_data.get('allowlist', [])) self.allowlist = set(json_data.get('allowlist', []))
logger.debug(f"Blocklist: {self.blocklist}")
logger.debug(f"Allowlist: {self.allowlist}")
# Fetch and cache the policy room ban lists # Fetch and cache the policy room ban lists
policy_banlist = yield self.fetch_policy_room_banlist() policy_banlist = yield self.fetch_policy_room_banlist()
logger.debug(f"Fetched policy banlist: {policy_banlist}")
self.blocklist.update(policy_banlist) # Merge policy bans into blocklist self.blocklist.update(policy_banlist) # Merge policy bans into blocklist
self.blocklist_room_ids = set() self.blocklist_room_ids = set()
@ -233,24 +222,30 @@ class InviteChecker:
logger.info(f"Allowing invite from {inviter} to {invitee} due to previous JSON fetch failure.") logger.info(f"Allowing invite from {inviter} to {invitee} due to previous JSON fetch failure.")
returnValue("NOT_SPAM") returnValue("NOT_SPAM")
blocklist, allowlist, blocklist_room_ids = yield self.get_blocklist_allowlist() try:
inviter_domain = UserID.from_string(inviter).domain blocklist, allowlist, blocklist_room_ids = yield self.get_blocklist_allowlist()
inviter_domain = UserID.from_string(inviter).domain
if self.use_allowlist and (inviter_domain in allowlist or inviter in allowlist): logger.debug(f"Blocklist: {blocklist}, Allowlist: {allowlist}, Blocklist Room IDs: {blocklist_room_ids}")
if self.use_allowlist and (inviter_domain in allowlist or inviter in allowlist):
returnValue("NOT_SPAM")
if room_id in blocklist_room_ids:
logger.info(f"Invite blocked: room {room_id} is blocklisted")
yield self.send_message_to_room(f"Invite from {inviter} to {invitee} blocked in room {room_id}. Reason: Blocklisted room.")
returnValue(errors.Codes.FORBIDDEN)
if self.use_blocklist and (inviter_domain in blocklist or inviter in blocklist):
logger.info(f"Invite blocked: {inviter} is blocklisted")
yield self.send_message_to_room(f"Invite from {inviter} to {invitee} blocked. Reason: Blocklisted.")
returnValue(errors.Codes.FORBIDDEN)
logger.info(f"Invite allowed by {inviter} for {invitee} in room {room_id}")
returnValue("NOT_SPAM") returnValue("NOT_SPAM")
except Exception as e:
if room_id in blocklist_room_ids: logger.error(f"Error during invite check: {str(e)} - {type(e).__name__}")
logger.info(f"Invite blocked: room {room_id} is blocklisted") returnValue("NOT_SPAM") # Fallback to allow the invite if an error occurs
yield self.send_message_to_room(f"Invite from {inviter} to {invitee} blocked in room {room_id}. Reason: Blocklisted room.")
returnValue(errors.Codes.FORBIDDEN)
if self.use_blocklist and (inviter_domain in blocklist or inviter in blocklist):
logger.info(f"Invite blocked: {inviter} is blocklisted")
yield self.send_message_to_room(f"Invite from {inviter} to {invitee} blocked. Reason: Blocklisted.")
returnValue(errors.Codes.FORBIDDEN)
logger.info(f"Invite allowed by {inviter} for {invitee} in room {room_id}")
returnValue("NOT_SPAM")
@inlineCallbacks @inlineCallbacks
def get_blocklist_allowlist(self): def get_blocklist_allowlist(self):