Skip to content

Commit

Permalink
Merge pull request #1292 from egbertbouman/fix_exit_relay
Browse files Browse the repository at this point in the history
Fixed relaying to exits
  • Loading branch information
egbertbouman committed Apr 10, 2024
2 parents e1f2e32 + c436e50 commit c17400e
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 31 deletions.
34 changes: 19 additions & 15 deletions ipv8/messaging/anonymization/community.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ def _ours_on_created_extended(self, circuit_id: int, payload: CreatedPayload | E
circuit.unverified_hop = None
circuit.add_hop(hop)
self.circuits.get(circuit_id) # Needed for notifying the RustEndpoint
self.logger.info("Added hop %d (%s) to circuit %d", len(circuit.hops), hop.peer, circuit.circuit_id)

if circuit.state == CIRCUIT_STATE_EXTENDING:
candidates_enc = payload.candidates_enc
Expand All @@ -592,30 +593,33 @@ def send_extend(self, circuit: Circuit, candidates: list[bytes], max_tries: int)
"""
Extend a circuit by choosing one of the given candidates.
"""
ignore_candidates = [hop.public_key_bin for hop in circuit.hops] + [self.my_peer.public_key.key_to_bin()]
if circuit.required_exit:
ignore_candidates.append(circuit.required_exit.public_key.key_to_bin())

become_exit = circuit.goal_hops - 1 == len(circuit.hops)
if become_exit and circuit.required_exit:
# Set the required exit according to the circuit setting (e.g. for linking e2e circuits)
extend_hop_public_bin = circuit.required_exit.public_key.key_to_bin()
extend_hop_addr = circuit.required_exit.address

else:
# The next candidate is chosen from the returned list of possible candidates
for ignore_candidate in ignore_candidates:
if ignore_candidate in candidates:
candidates.remove(ignore_candidate)

for i in range(len(candidates) - 1, -1, -1):
public_key = self.crypto.key_from_public_bin(candidates[i])
if not self.crypto.is_key_compatible(public_key):
candidates.pop(i)

# Chose the next candidate. Ensure we didn't use this candidate already, and its key is compatible.
exclude = [hop.public_key_bin for hop in circuit.hops] + [self.my_peer.public_key.key_to_bin()]
if circuit.required_exit:
exclude.append(circuit.required_exit.public_key.key_to_bin())
candidates = [c for c in candidates if c not in exclude and self.crypto.key_from_public_bin(c)]
extend_hop_public_bin = next(iter(candidates), b'')
extend_hop_addr = ('0.0.0.0', 0)

if not extend_hop_public_bin:
# By default, nodes will give a number of relays to which we can extend the circuit (i.e., peers
# that have already been punctured). However, it could be that there simply aren't enough relays
# available. When this happens, we try to extend to exit nodes (which we assume are connectable).
choices = [peer for peer in self.get_candidates(PEER_FLAG_EXIT_BT, PEER_FLAG_RELAY)
if peer.public_key.key_to_bin() not in exclude]
if choices:
peer = random.choice(choices)
extend_hop_public_bin = peer.public_key.key_to_bin()
extend_hop_addr = peer.address
self.logger.info('No candidates to extend to, trying exit node %s instead', peer)

if extend_hop_public_bin:
if self.request_cache.has(RetryRequestCache, circuit.circuit_id):
self.request_cache.pop(RetryRequestCache, circuit.circuit_id)
Expand Down Expand Up @@ -751,10 +755,10 @@ def join_circuit(self, create_payload: CreatePayload, previous_node_address: Add

peer = Peer(create_payload.node_public_key, previous_node_address)
self.request_cache.add(CreatedRequestCache(self, circuit_id, peer, peers_keys, self.settings.unstable_timeout))
self.exit_sockets[circuit_id] = TunnelExitSocket(circuit_id, Hop(peer, session_keys), self)

candidates_bin = self.serializer.pack('varlenH-list', list(peers_keys.keys()))
candidates_enc = self.crypto.encrypt_str(candidates_bin, session_keys, FORWARD)
self.exit_sockets[circuit_id] = TunnelExitSocket(circuit_id, Hop(peer, session_keys), self)
self.send_cell(previous_node_address,
CreatedPayload(circuit_id, create_payload.identifier, key, auth, candidates_enc))

Expand Down
2 changes: 1 addition & 1 deletion ipv8/messaging/anonymization/hidden_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,12 +471,12 @@ def create_created_e2e(self, rp: RendezvousPoint, source_address: Address,
key = self.swarms[payload.info_hash].seeder_sk
shared_secret, y, auth = self.crypto.generate_diffie_shared_secret(payload.key, key)
rp.circuit.hs_session_keys = self.crypto.generate_session_keys(shared_secret)
self.circuits.get(rp.circuit.circuit_id) # Needed for notifying the RustEndpoint

rp_info = RendezvousInfo(rp.address, rp.circuit.hops[-1].public_key.key_to_bin(), rp.cookie)
rp_info_bin = self.serializer.pack('payload', rp_info)
rp_info_enc = self.crypto.encrypt_str(rp_info_bin, rp.circuit.hs_session_keys, FORWARD)

self.circuits.get(rp.circuit.circuit_id) # Needed for notifying the RustEndpoint
circuit = self.circuits[cast(int, circuit_id)]
self.tunnel_data(circuit, source_address, CreatedE2EPayload(payload.identifier, y, auth, rp_info_enc))

Expand Down
22 changes: 7 additions & 15 deletions run_all_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,21 +259,13 @@ def install_libsodium() -> None:
"""
# Ensure a libsodium.zip
if not pathlib.Path("libsodium.zip").exists():
import re
from http.client import HTTPSConnection
connection = HTTPSConnection("download.libsodium.org")

connection.request("GET", "/libsodium/releases/", headers={})
web_response = connection.getresponse().read().decode()

# Extract the latest version
result = sorted(re.findall(r"libsodium-[0-9]*\.[0-9]*\.[0-9]*-stable-msvc.zip\"",
web_response))[-1][:-1]

connection.request("GET", f"/libsodium/releases/{result}", headers={})
pathlib.Path("libsodium.zip").write_bytes(connection.getresponse().read())

connection.close()
import json
import urllib.request as request
response = request.urlopen("https://api.github.com/repos/jedisct1/libsodium/releases")
release = json.loads(response.read())[0]
response.close()
asset = [asset for asset in release['assets'] if asset['name'].endswith("-msvc.zip")][0]
pathlib.Path("libsodium.zip").write_bytes(request.urlopen(asset['browser_download_url']).read())

# Unpack just the libsodium.dll
if not pathlib.Path("libsodium.dll").exists():
Expand Down

0 comments on commit c17400e

Please sign in to comment.