Bypassing connection tracking for BitTorrent traffic
Feb 9, 2015iptables
doesn’t like torrent traffic. More specifically, its connection
tracker (dubbed conntrack
) easily gets confused by connections to and from the
swarm. In order to get all traffic through, I decided to bypass connection
tracking for BitTorrent traffic, which has significantly improved my up- and
downloading speeds!
The most common problem with tracking BitTorrent connections is the high volume
of them, causing internal state tables to
overflow. I bumped into
another issue, where certain incoming RST
-flagged packets got blocked, much
like how
this forum post
details. This thoroughly messed with my torrent client, which got stuck with
many closed connections thinking they were still valid.
I ultimately decided to get rid of connection tracking for BitTorrent traffic
altogether. By marking packages NOTRACK
in the respective raw
tables, we
instruct iptables
not to track these packages. However, this also means losing
some helpful functionality. conntrack
and NAT helper will simply not work, and
we’ll need to handle ICMP errors ourselves. Luckily, BitTorrent traffic is not
state-full (as opposed to, for example, FTP), so we don’t need any helpers.
The following snippet lists the required iptables
commands (usable with
ip6tables
too):
# BitTorrent "server"
SERVER="40000"
for PROTO in tcp udp; do
# incoming traffic
iptables -t raw -I PREROUTING -p $PROTO \
--dport ${SERVER} -j NOTRACK
iptables -I INPUT -i eth0 -p $PROTO \
--dport ${SERVER} -j ACCEPT
# outgoing traffic (replies)
iptables -t raw -I OUTPUT -p $PROTO \
--sport ${SERVER} -j NOTRACK
iptables -I OUTPUT -p $PROTO \
--sport ${SERVER} -j ACCEPT
done
# BitTorrent "client"
CLIENT="40001:40999"
for PROTO in tcp udp; do
# outgoing traffic
iptables -t raw -I OUTPUT -p $PROTO \
--sport ${CLIENT} -j NOTRACK
iptables -I OUTPUT -p $PROTO \
--sport ${CLIENT} -j ACCEPT
# incoming traffic (replies)
iptables -t raw -I PREROUTING -p $PROTO \
--dport ${CLIENT} -j NOTRACK
iptables -I INPUT -i eth0 -p $PROTO \
--dport ${CLIENT} -j ACCEPT
done
Recall that due to marking all packages NOTRACK
, iptables
will not be able
to tie ICMP replies to the corresponding connection, and as a result treat those
packages as invalid. To resolve this, we should explicitly allow such control
messages:
for TYPE in destination-unreachable source-quench \
ttl-exceeded parameter-problem; do
iptables -I INPUT -p icmp \
--icmp-type $TYPE -j ACCEPT
iptables -I OUTPUT -p icmp \
--icmp-type $TYPE -j ACCEPT
done
for TYPE in destination-unreachable packet-too-big \
ttl-exceeded parameter-problem; do
ip6tables -I INPUT -p icmpv6 \
--icmpv6-type $TYPE -j ACCEPT
ip6tables -I OUTPUT -p icmpv6 \
--icmpv6-type $TYPE -j ACCEPT
done
If required, you could still tighten these rules up a bit. Some ideas:
- restrict outgoing traffic with
--uid-owner
- limit the allowed ICMP datagrams based on the original IP payload (for
instance, using the
u32
extension)