Skip to content

Commit

Permalink
Optionally restrict the range of ephemeral ports
Browse files Browse the repository at this point in the history
  • Loading branch information
sirf committed Oct 26, 2022
1 parent f08956b commit a9d94e4
Showing 1 changed file with 32 additions and 4 deletions.
36 changes: 32 additions & 4 deletions src/aioice/ice.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ class Connection:
:param turn_transport: The transport for TURN server, `"udp"` or `"tcp"`.
:param use_ipv4: Whether to use IPv4 candidates.
:param use_ipv6: Whether to use IPv6 candidates.
:param port_lower: The lowest port to bind to.
:param port_upper: The highest port to bind to.
"""

def __init__(
Expand All @@ -296,6 +298,8 @@ def __init__(
turn_transport: str = "udp",
use_ipv4: bool = True,
use_ipv6: bool = True,
port_lower: int = 0,
port_upper: int = 0,
) -> None:
self.ice_controlling = ice_controlling
#: Local username, automatically set to a random value.
Expand Down Expand Up @@ -340,6 +344,8 @@ def __init__(
self._tie_breaker = secrets.randbits(64)
self._use_ipv4 = use_ipv4
self._use_ipv6 = use_ipv6
self._port_lower = port_lower
self._port_upper = port_upper

@property
def local_candidates(self) -> List[Candidate]:
Expand Down Expand Up @@ -843,20 +849,42 @@ def _find_pair(
return pair
return None

async def _create_datagram_endpoint(self, address):
"""
Create a datagram endpoint on the specified address,
with port optionally in the range [port_lower, port_upper]
"""
# when port_lower and port_upper are both zero: ports = [0]
# which will let the OS pick any random free port
ports = list(range(
self._port_lower if self._port_lower or not self._port_upper else 1,
(65535 if self._port_lower and not self._port_upper else self._port_upper) + 1
))
random.shuffle(ports)
loop = asyncio.get_event_loop()
for port in ports:
try:
transport, protocol = await loop.create_datagram_endpoint(
lambda: StunProtocol(self), local_addr=(address, port)
)
return transport, protocol
except OSError as exc:
if port == ports[-1]:
# this was the last port, give up
raise exc
raise ValueError("Illegal port range: [%d, %d]" % (self._port_lower, self._port_upper))

async def get_component_candidates(
self, component: int, addresses: List[str], timeout: int = 5
) -> List[Candidate]:
candidates = []
loop = asyncio.get_event_loop()

# gather host candidates
host_protocols = []
for address in addresses:
# create transport
try:
transport, protocol = await loop.create_datagram_endpoint(
lambda: StunProtocol(self), local_addr=(address, 0)
)
transport, protocol = await self._create_datagram_endpoint(address)
sock = transport.get_extra_info("socket")
if sock is not None:
sock.setsockopt(
Expand Down

0 comments on commit a9d94e4

Please sign in to comment.