Merge branch 'block_relays' into 'master'
Block relays See merge request pleroma/relay!26
This commit is contained in:
commit
83d56cb570
|
@ -20,4 +20,11 @@ ap:
|
|||
whitelist_enabled: false
|
||||
whitelist:
|
||||
- 'good-instance.example.com'
|
||||
- 'another.good-instance.example.com'
|
||||
- 'another.good-instance.example.com'
|
||||
# uncomment the lines below to prevent certain activitypub software from posting
|
||||
# to the relay (all known relays by default). this uses the software name in nodeinfo
|
||||
#blocked_software:
|
||||
#- 'activityrelay'
|
||||
#- 'aoderelay'
|
||||
#- 'social.seattle.wa.us-relay'
|
||||
#- 'unciarelay'
|
||||
|
|
|
@ -9,9 +9,13 @@ import yaml
|
|||
|
||||
def load_config():
|
||||
with open('relay.yaml') as f:
|
||||
yaml_file = yaml.load(f)
|
||||
whitelist = yaml_file['ap'].get('whitelist', [])
|
||||
blocked = yaml_file['ap'].get('blocked_instances', [])
|
||||
options = {}
|
||||
|
||||
## Prevent a warning message for pyyaml 5.1+
|
||||
if getattr(yaml, 'FullLoader', None):
|
||||
options['Loader'] = yaml.FullLoader
|
||||
|
||||
yaml_file = yaml.load(f, **options)
|
||||
|
||||
config = {
|
||||
'db': yaml_file.get('db', 'relay.jsonld'),
|
||||
|
@ -19,9 +23,10 @@ def load_config():
|
|||
'port': int(yaml_file.get('port', 8080)),
|
||||
'note': yaml_file.get('note', 'Make a note about your instance here.'),
|
||||
'ap': {
|
||||
'blocked_instances': [] if blocked is None else blocked,
|
||||
'blocked_software': [v.lower() for v in yaml_file['ap'].get('blocked_software', [])],
|
||||
'blocked_instances': yaml_file['ap'].get('blocked_instances', []),
|
||||
'host': yaml_file['ap'].get('host', 'localhost'),
|
||||
'whitelist': [] if whitelist is None else whitelist,
|
||||
'whitelist': yaml_file['ap'].get('whitelist', []),
|
||||
'whitelist_enabled': yaml_file['ap'].get('whitelist_enabled', False)
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +35,6 @@ def load_config():
|
|||
|
||||
CONFIG = load_config()
|
||||
|
||||
|
||||
from .http_signatures import http_signatures_middleware
|
||||
|
||||
|
||||
|
|
|
@ -103,6 +103,29 @@ async def push_message_to_actor(actor, message, our_key_id):
|
|||
logging.info('Caught %r while pushing to %r.', e, inbox)
|
||||
|
||||
|
||||
async def fetch_nodeinfo(domain):
|
||||
headers = {'Accept': 'application/json'}
|
||||
nodeinfo_url = None
|
||||
|
||||
wk_nodeinfo = await fetch_actor(f'https://{domain}/.well-known/nodeinfo', headers=headers)
|
||||
|
||||
if not wk_nodeinfo:
|
||||
return
|
||||
|
||||
for link in wk_nodeinfo.get('links', ''):
|
||||
if link['rel'] == 'http://nodeinfo.diaspora.software/ns/schema/2.0':
|
||||
nodeinfo_url = link['href']
|
||||
break
|
||||
|
||||
if not nodeinfo_url:
|
||||
return
|
||||
|
||||
nodeinfo_data = await fetch_actor(nodeinfo_url, headers=headers)
|
||||
software = nodeinfo_data.get('software')
|
||||
|
||||
return software.get('name') if software else None
|
||||
|
||||
|
||||
async def follow_remote_actor(actor_uri):
|
||||
actor = await fetch_actor(actor_uri)
|
||||
|
||||
|
@ -235,6 +258,7 @@ async def handle_follow(actor, data, request):
|
|||
following = DATABASE.get('relay-list', [])
|
||||
inbox = get_actor_inbox(actor)
|
||||
|
||||
|
||||
if urlsplit(inbox).hostname in AP_CONFIG['blocked_instances']:
|
||||
return
|
||||
|
||||
|
@ -294,6 +318,12 @@ async def inbox(request):
|
|||
data = await request.json()
|
||||
instance = urlsplit(data['actor']).hostname
|
||||
|
||||
if AP_CONFIG['blocked_software']:
|
||||
software = await fetch_nodeinfo(instance)
|
||||
|
||||
if software and software.lower() in AP_CONFIG['blocked_software']:
|
||||
raise aiohttp.web.HTTPUnauthorized(body='relays have been blocked', content_type='text/plain')
|
||||
|
||||
if 'actor' not in data or not request['validated']:
|
||||
raise aiohttp.web.HTTPUnauthorized(body='access denied', content_type='text/plain')
|
||||
|
||||
|
|
|
@ -12,13 +12,18 @@ CACHE_TTL = CONFIG.get('cache-ttl', 3600)
|
|||
ACTORS = TTLCache(CACHE_SIZE, CACHE_TTL)
|
||||
|
||||
|
||||
async def fetch_actor(uri, force=False):
|
||||
async def fetch_actor(uri, headers={}, force=False):
|
||||
if uri in ACTORS and not force:
|
||||
return ACTORS[uri]
|
||||
|
||||
new_headers = {'Accept': 'application/activity+json'}
|
||||
|
||||
for k,v in headers.items():
|
||||
new_headers[k.capitalize()] = v
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession(trace_configs=[http_debug()]) as session:
|
||||
async with session.get(uri, headers={'Accept': 'application/activity+json'}) as resp:
|
||||
async with session.get(uri, headers=new_headers) as resp:
|
||||
if resp.status != 200:
|
||||
return None
|
||||
ACTORS[uri] = (await resp.json(encoding='utf-8', content_type=None))
|
||||
|
|
|
@ -6,7 +6,7 @@ idna==2.7
|
|||
idna-ssl==1.1.0
|
||||
multidict==4.3.1
|
||||
pycryptodome==3.9.4
|
||||
PyYAML==3.13
|
||||
PyYAML>=5.1
|
||||
simplejson==3.16.0
|
||||
yarl==1.2.6
|
||||
cachetools
|
||||
|
|
Loading…
Reference in a new issue