Skip to content

Commit

Permalink
Merge pull request #6180 from egbertbouman/dns_leak_fix
Browse files Browse the repository at this point in the history
Fix DNS leak in TorrentChecker
  • Loading branch information
egbertbouman authored Jun 24, 2021
2 parents 3165a72 + 6c3a6c1 commit 99e624f
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/tribler-core/run_tunnel_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def main(argv):
parser.add_argument('--ipv8_address', '-i', default='0.0.0.0', type=str, help='IPv8 listening address', action=IPAction)
parser.add_argument('--ipv8_bootstrap_override', '-b', default=None, type=str,
help='Force the usage of specific IPv8 bootstrap server (ip:port)', action=IPPortAction)
parser.add_argument('--restapi', '-p', default=52194, type=str,
parser.add_argument('--restapi', '-p', default=52194, type=int,
help='Use an alternate port for the REST API', action=PortAction, metavar='{0..65535}')
parser.add_argument('--cert-file', '-e', help='Path to combined certificate/key file. If not given HTTP is used.')
parser.add_argument('--api-key', '-k', help='API key to use. If not given API key protection is disabled.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,9 @@ async def check_torrent_health(self, infohash, timeout=20, scrape_now=False):
# get torrent's tracker list from DB
tracker_set = self.get_valid_trackers_of_torrent(torrent_id)

hops = self.tribler_session.config.get_default_number_hops()
socks_listen_ports = self.tribler_session.config.get_tunnel_community_socks5_listen_ports()
proxy = ('127.0.0.1', socks_listen_ports[hops - 1]) if hops > 0 else None

tasks = []
for tracker_url in tracker_set:
session = self._create_session_for_request(tracker_url, timeout=timeout, proxy=proxy)
session = self._create_session_for_request(tracker_url, timeout=timeout)
session.add_infohash(infohash)
tasks.append(self.connect_to_tracker(session))

Expand All @@ -346,7 +342,10 @@ async def check_torrent_health(self, infohash, timeout=20, scrape_now=False):
res = await gather(*tasks, return_exceptions=True)
return self.on_torrent_health_check_completed(infohash, res)

def _create_session_for_request(self, tracker_url, timeout=20, proxy=None):
def _create_session_for_request(self, tracker_url, timeout=20):
hops = self.tribler_session.config.get_default_number_hops()
socks_listen_ports = self.tribler_session.config.get_tunnel_community_socks5_listen_ports()
proxy = ('127.0.0.1', socks_listen_ports[hops - 1]) if hops > 0 else None
session = create_tracker_session(tracker_url, timeout, proxy, self.socket_mgr)

if tracker_url not in self._session_list:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ async def send_request(self, data, tracker_session):
if proxy not in self.proxy_transports:
self.proxy_transports[proxy] = transport

host = tracker_session.ip_address or tracker_session.tracker_address[0]
try:
transport.sendto(data, (tracker_session.ip_address, tracker_session.port))
transport.sendto(data, (host, tracker_session.port))
f = self.tracker_sessions[tracker_session.transaction_id] = Future()
return await f
except OSError as e:
Expand Down Expand Up @@ -321,13 +322,16 @@ async def connect_to_tracker(self):

try:
async with async_timeout.timeout(self.timeout):
# Resolve the hostname to an IP address if not done already
coro = get_event_loop().getaddrinfo(self.tracker_address[0], 0, family=socket.AF_INET)
if isinstance(coro, Future):
infos = await coro # In Python <=3.6 getaddrinfo returns a Future
else:
infos = await self.register_anonymous_task("resolve", ensure_future(coro))
self.ip_address = infos[0][-1][0]
# We only resolve the hostname if we're not using a proxy.
# If a proxy is used, the TunnelCommunity will resolve the hostname at the exit nodes.
if not self.proxy:
# Resolve the hostname to an IP address if not done already
coro = get_event_loop().getaddrinfo(self.tracker_address[0], 0, family=socket.AF_INET)
if isinstance(coro, Future):
infos = await coro # In Python <=3.6 getaddrinfo returns a Future
else:
infos = await self.register_anonymous_task("resolve", ensure_future(coro))
self.ip_address = infos[0][-1][0]
await self.connect()
return await self.scrape()
except TimeoutError:
Expand Down
5 changes: 5 additions & 0 deletions src/tribler-core/tribler_core/modules/tunnel/socks5/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ipaddress
import logging
import socket
from asyncio import DatagramProtocol, Protocol, Queue, get_event_loop
Expand Down Expand Up @@ -43,6 +44,10 @@ def datagram_received(self, data, _):
self.callback(request.data, request.destination)

def sendto(self, data, target_addr):
try:
ipaddress.IPv4Address(target_addr[0])
except ipaddress.AddressValueError:
target_addr = DomainAddress(*target_addr)
packet = socks5_serializer.pack_serializable(UdpPacket(0, 0, target_addr, data))
self.transport.sendto(packet, self.proxy_udp_addr)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ async def test_start_server(socks5_server):
@pytest.mark.asyncio
async def test_socks5_udp_associate(socks5_server):
"""
Test is sending a UDP associate request to the server succeeds.
Test if sending a UDP associate request to the server succeeds.
"""
await socks5_server.start()
client = Socks5Client(('127.0.0.1', socks5_server.port), Mock())
Expand Down Expand Up @@ -79,7 +79,7 @@ async def test_socks5_sendto_success(socks5_server):
@pytest.mark.asyncio
async def test_socks5_tcp_connect(socks5_server):
"""
Test is sending a TCP connect request to the server succeeds.
Test if sending a TCP connect request to the server succeeds.
"""
await socks5_server.start()
client = Socks5Client(('127.0.0.1', socks5_server.port), Mock())
Expand All @@ -91,7 +91,7 @@ async def test_socks5_tcp_connect(socks5_server):
@pytest.mark.asyncio
async def test_socks5_write(socks5_server):
"""
Test is sending a TCP data to the server succeeds.
Test if sending a TCP data to the server succeeds.
"""
await socks5_server.start()
client = Socks5Client(('127.0.0.1', socks5_server.port), Mock())
Expand Down

0 comments on commit 99e624f

Please sign in to comment.