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_enabled: false
|
||||||
whitelist:
|
whitelist:
|
||||||
- 'good-instance.example.com'
|
- '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():
|
def load_config():
|
||||||
with open('relay.yaml') as f:
|
with open('relay.yaml') as f:
|
||||||
yaml_file = yaml.load(f)
|
options = {}
|
||||||
whitelist = yaml_file['ap'].get('whitelist', [])
|
|
||||||
blocked = yaml_file['ap'].get('blocked_instances', [])
|
## Prevent a warning message for pyyaml 5.1+
|
||||||
|
if getattr(yaml, 'FullLoader', None):
|
||||||
|
options['Loader'] = yaml.FullLoader
|
||||||
|
|
||||||
|
yaml_file = yaml.load(f, **options)
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
'db': yaml_file.get('db', 'relay.jsonld'),
|
'db': yaml_file.get('db', 'relay.jsonld'),
|
||||||
|
@ -19,9 +23,10 @@ def load_config():
|
||||||
'port': int(yaml_file.get('port', 8080)),
|
'port': int(yaml_file.get('port', 8080)),
|
||||||
'note': yaml_file.get('note', 'Make a note about your instance here.'),
|
'note': yaml_file.get('note', 'Make a note about your instance here.'),
|
||||||
'ap': {
|
'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'),
|
'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)
|
'whitelist_enabled': yaml_file['ap'].get('whitelist_enabled', False)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +35,6 @@ def load_config():
|
||||||
|
|
||||||
CONFIG = load_config()
|
CONFIG = load_config()
|
||||||
|
|
||||||
|
|
||||||
from .http_signatures import http_signatures_middleware
|
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)
|
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):
|
async def follow_remote_actor(actor_uri):
|
||||||
actor = await fetch_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', [])
|
following = DATABASE.get('relay-list', [])
|
||||||
inbox = get_actor_inbox(actor)
|
inbox = get_actor_inbox(actor)
|
||||||
|
|
||||||
|
|
||||||
if urlsplit(inbox).hostname in AP_CONFIG['blocked_instances']:
|
if urlsplit(inbox).hostname in AP_CONFIG['blocked_instances']:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -294,6 +318,12 @@ async def inbox(request):
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
instance = urlsplit(data['actor']).hostname
|
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']:
|
if 'actor' not in data or not request['validated']:
|
||||||
raise aiohttp.web.HTTPUnauthorized(body='access denied', content_type='text/plain')
|
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)
|
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:
|
if uri in ACTORS and not force:
|
||||||
return ACTORS[uri]
|
return ACTORS[uri]
|
||||||
|
|
||||||
|
new_headers = {'Accept': 'application/activity+json'}
|
||||||
|
|
||||||
|
for k,v in headers.items():
|
||||||
|
new_headers[k.capitalize()] = v
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession(trace_configs=[http_debug()]) as session:
|
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:
|
if resp.status != 200:
|
||||||
return None
|
return None
|
||||||
ACTORS[uri] = (await resp.json(encoding='utf-8', content_type=None))
|
ACTORS[uri] = (await resp.json(encoding='utf-8', content_type=None))
|
||||||
|
|
|
@ -6,7 +6,7 @@ idna==2.7
|
||||||
idna-ssl==1.1.0
|
idna-ssl==1.1.0
|
||||||
multidict==4.3.1
|
multidict==4.3.1
|
||||||
pycryptodome==3.9.4
|
pycryptodome==3.9.4
|
||||||
PyYAML==3.13
|
PyYAML>=5.1
|
||||||
simplejson==3.16.0
|
simplejson==3.16.0
|
||||||
yarl==1.2.6
|
yarl==1.2.6
|
||||||
cachetools
|
cachetools
|
||||||
|
|
Loading…
Reference in New Issue