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 time
import os
@ -49,61 +49,45 @@ class InviteChecker:
self.api.register_spam_checker_callbacks(user_may_invite=self.user_may_invite)
logger.info("InviteChecker initialized")
@inlineCallbacks
def fetch_json(self, url):
logger.info(f"Fetching JSON data from: {url}")
# Fetch proxy from the environment variable
https_proxy = os.getenv('https_proxy')
headers = None # Initialize headers to None
# Read proxy configuration from the environment variable 'https_proxy', if set
https_proxy = os.getenv('https_proxy', None)
proxies = {}
if https_proxy:
logger.info(f"Using HTTPS proxy: {https_proxy}")
# Parse the proxy URL with optional username and password
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}']
})
# Mask credentials in the proxy URL
if '@' in https_proxy:
masked_proxy = '****:****@' + https_proxy.split('@')[1]
else:
headers = None
proxy_host, proxy_port = https_proxy.split(':')
masked_proxy = https_proxy
proxy_endpoint = TCP4ClientEndpoint(reactor, proxy_host, int(proxy_port))
# Create a ProxyAgent with authentication if needed
agent = ProxyAgent(proxy_endpoint)
proxies = {
"https": https_proxy
}
logger.info(f"Using HTTPS proxy: {masked_proxy}")
else:
# If no proxy is set, use the default agent
agent = Agent(reactor)
logger.info("No proxy configured, making direct request")
try:
# Pass headers to the request if authentication is required
if headers:
response = yield treq.get(url, agent=agent, headers=headers)
else:
response = yield treq.get(url, agent=agent)
# Make the request with the proxy if set, otherwise direct
response = requests.get(url, proxies=proxies, timeout=10)
if response.code == 200:
content = yield response.content()
data = json.loads(content.decode('utf-8'))
# Log the response status code
logger.info(f"Received response with status code: {response.status_code}")
# Check for a successful response
if response.status_code == 200:
data = response.json() # Parse the JSON data
logger.debug(f"Received JSON data: {data}")
returnValue(data)
return data
else:
logger.error(f"Failed to fetch JSON data. Status code: {response.code}")
returnValue(None)
logger.error(f"Non-200 response code: {response.status_code}, Response body: {response.text}")
return None
except Exception as e:
logger.error(f"Error while fetching JSON: {str(e)}")
returnValue(None)
logger.error(f"Error while fetching JSON: {str(e)} - {type(e).__name__}")
return None
@inlineCallbacks
def fetch_policy_room_banlist(self):
@ -153,17 +137,22 @@ class InviteChecker:
"""Fetch and update the blocklist, allowlist, and blocklisted room IDs."""
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:
logger.debug(f"Fetched JSON data: {json_data}") # Log the full JSON data for verification
self.allow_all_invites_on_error = False
self.use_allowlist = json_data.get('use_allowlist', True)
self.use_blocklist = json_data.get('use_blocklist', True)
self.blocklist = set(json_data.get('blocklist', []))
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
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_room_ids = set()
@ -233,24 +222,30 @@ class InviteChecker:
logger.info(f"Allowing invite from {inviter} to {invitee} due to previous JSON fetch failure.")
returnValue("NOT_SPAM")
blocklist, allowlist, blocklist_room_ids = yield self.get_blocklist_allowlist()
inviter_domain = UserID.from_string(inviter).domain
try:
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")
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")
except Exception as e:
logger.error(f"Error during invite check: {str(e)} - {type(e).__name__}")
returnValue("NOT_SPAM") # Fallback to allow the invite if an error occurs
@inlineCallbacks
def get_blocklist_allowlist(self):