Background
If you have a working BOPM installation, you are trying to prevent abuses of your IRC network effected through anonymity services such as proxies. BOPM has built-in support for scanning for open proxies. It also has support for looking up clients in DNSBLs, which are used to publish lists of misbehaving or malign hosts. One such DNSBL, called TorDNSEL, provides a way to check users connecting through the Tor anonymity service.
As discussed at TorDNSEL’s information page, the purpose of this service is to provide finely-grained information about whether a client’s connection could be through a Tor exit node. Tor exit nodes can be configured with advanced exit policies which specify the sorts of direct outbound connections a Tor exit node is willing to make on behalf of its anonymous client. For example, a Tor exit node administrator could disallow his node to make connections to government sites and disable outgoing connections on common IRC ports. If a Tor exit node is run by an administrator who is interested in also connecting to an IRC network, that administrator would disallow outgoing IRC connections. Thus, any IRC connection made (on a common IRC port) through that node would be a legitimate connection made by a user on that host and not a connection from an anonymous client. The TorDNSEL DNSBL lets—and requires—networks which use it to take this into account.
Prerequisites
This short guide assumes that you have successfully configured BOPM to connect to your IRCd, parse oper notices informing it of client connections, and issue a G/Z:line or SHUN for some other event which identifies a client as using a particular anonymity service.
Configuring BOPM
As TorDNSEL’s information page documents, performing a TorDNSEL lookup requires the IRC client’s IP A.B.C.D
, the port of the service being accessed P
, and the public IP of the IRCd E.F.G.H
. With these parameters, a query would be an A record lookup of the domain name D.C.B.A.P.H.G.F.E.ip-port.exitlist.torproject.org
. If the response was NXDOMAIN
, then either there is no Tor exit node at A.B.C.D
or, if that IP identifies an exit node, that node is unwilling to connect to E.F.G.H
on port P
because its exit policy forbids such a connection. If the response is 127.0.0.2
, then there is a Tor exit node at A.B.C.D
which would willying connect to E.F.G.H
on port P
. From this information, we can produce a BOPM blacklist block:
OPM {
# …
blacklist {
name = "P.H.G.F.E.ip-port.exitlist.torproject.org";
type = "A record reply";
reply {
2 = "Tor exit server";
};
ban_unknown = yes;
# GZLINE issuing a 7-day network-wide zline with UnrealIRCd-compatible syntax
kline = "GZLINE *@%i 7d :You are connecting from a Tor exit node willing to connect to E.F.G.H:P";
};
# …
};
The above blacklist
should be copy-pastable into your bopm.conf
‘s OPM
section. But, remember to replace E
, F
, G
, and H
with the respective components of your IRCd’s IP address. In the name
line, it is intended that the components of the IP are in reverse order. This is because the right end of a domain is more general and the left end is more specific whereas in the first component of an IP address is most general and the rightmost component is more specific.
Also, note that you shouldn’t copy the …
into your bopm.conf
; each of these is just a placeholder indicating that you probably already have other blacklist
blocks which should be preserved defined inside the OPM
block.
One last note about this blacklist entry. If your IRC network, like many networks, allows connections to multiple ports, you must specify a blacklist
entry for each port. For example, 6667 is the port an IRC client will try, by default, to use when connecting to an IRCd. But if a client wants to use SSL (without STARTTLS), you might have instructed your IRCd to listen for SSL connections on port 6697. A side effect of TorDNSEL’s specific entries is that a tor exit node may be instructed to deny outbound connections on port 6667 yet allow them on 6697. Since BOPM cannot (AFAIK) be configured to automatically choose a value for P
, you must create a blacklist
block for each IRCd public IP and port combination.
Breakdown
OPM {
# …
blacklist {
name = "P.H.G.F.E.ip-port.exitlist.torproject.org";
Here you specify your server’s public IP, E.F.G.H
, in reverse as H.G.F.E
as well as the port your IRCd is listening on, P
. BOPM will prepend the IP of the IRC client which connects, A.B.C.D
, in reverse order as D.C.B.A
when it checks if the client is in this TorDNSEL.
type = "A record reply";
This specifies that BOMP should take the IP address the DNSBL returns and interpret that as a response. DNSBLs generally use IPs in the reserved localhost range, 127.0.0.0/8
, to avoid pointing to IPs owned by third parties.
reply {
2 = "Tor exit server";
};
This is the list of potential DNSBL responses which you anticipate from TorDNSEL. If the DNSBL returns NXDOMAIN
(which means, “I don’t know about this doain”), BOPM will ignore the answer and assume the client is not in the DNSBL. However, if the server responds with an IP such as 127.0.0.2
, BOPM will subtract 127.0.0.0
from the IP and then look for the result 2
in this reply list. If it finds an entry, it performs the action in kline
discussed below.
TorDNSEL currently only defines two possible responses. NXDOMAIN
indicates that the node would not connect to E.F.G.H:P
on behalf of a Tor client. 127.0.0.2
or, as BOPM interprets it, 2
indicates that there is a Tor exit node at A.B.C.D
which is willing to connect to your IRCd.
ban_unknown = yes;
This line states that, if the DNSBL responds with an IP other than those handled in the reply
block, it should assume that the client still should be banned. The TorDNSEL guide states Other A records inside net 127/8, except 127.0.0.1, are reserved for future use and should be interpreted by clients as indicating an exit node.
This means that the TorDNSEL project reserves the right to add a new response, such as 127.0.0.3
, which would indicate a subtly different sort of tor exit node. Until this new response is defined, all we know is that the IRC client probably should be banned by BOPM.
# GZLINE issuing a 7-day network-wide zline with UnrealIRCd-compatible syntax
kline = "GZLINE *@%i 7d :You are connecting from a Tor exit node willing to connect to E.F.G.H:P";
This is the IRC command which BOPM will issue when a client is listed in TorDNSEL. The above command will set a network-wide ban on the user’s IP which will last for 7 days using UnrealIRCd‘s syntax. A Global Z:Line is an efficient ban as the client’s connection can be closed by the IRCd before the IRCd looks up the client’s hostname. The reason listed with the GZ:Line is formulated so that the IRC user will understand exactly why he was banned.
};
# …
};
Be careful when editing your bopm.conf. Don’t forget any semicolons; even the ones after closing curly braces (}
) are ncessary. If you’re reading this guide, you hopefully don’t need this advice ;-).
Testing
Once you have added the necessary configuration directives to your bopm.conf
, you should test and check that BOPM catches the Tor exit nodes which are willing to connect to your IRCd. If BOPM was already running, do not forget to rehash it (BOPM’s readme suggests that /KILL BOPM (rehashing)
is a convenient way to force BOPM to reread its configuration and reconnect). The following uses BOPM’s in-channel command interface to ask BOPM to scan an IP and check if it would be banned if a client connected from that IP. This requires that you have properly configured BOPM to join a channel with an IRC::channel
block. An alternative test would be to just connect to your network through Tor, but that is probably more involved.
To check if your BOPM would detect a Tor IP, first find a Tor exit node (if using list list, ensure to choose an IP for which the “Exit Node?” column has “YES”). Then join the channel where BOPM is and issue the command BOPM check IP
, where you replace BOPM
with the nickname your BOPM bot is using and replace IP
with the Tor exit node IP you looked up. A successful detection will look something like the following:
-!- BOPM2 [~bopm@Clk-NNNNNNNN] has joined #opers <&binki> BOPM2 check A.B.C.D < BOPM2> CHECK -> Checking 'A.B.C.D' for open proxies on all scanners < BOPM2> CHECK -> DNSBL -> A.B.C.D appears in BL zone 6667.H.G.F.E.ip-port.exitlist.torproject.org (Tor exit server) < BOPM2> CHECK -> DNSBL -> A.B.C.D appears in BL zone 6697.H.G.F.E.ip-port.exitlist.torproject.org (Tor exit server) < BOPM2> CHECK -> DNSBL -> A.B.C.D does not appear in BL zone 6900.H.G.F.E.ip-port.exitlist.torproject.org < BOPM2> CHECK -> DNSBL -> A.B.C.D appears in BL zone 7000.H.G.F.E.ip-port.exitlist.torproject.org (Tor exit server) < BOPM2> CHECK -> All tests on A.B.C.D completed.
In this scenario, the port 6900 was inside of a reject range policy on the Tor exit node I selected. For some odd reason, it seems that this port is part of a range which is commonly disabled in Tor exit nodes. Yet, the Tor exit node I chose admits that it is willing to connect to my IRCd still and will be banned because of one of the other OPM::blacklist
blocks I have defined, such as the one for port 6667.
In your own tests, you might encounter Tor exit nodes which BOPM does not flag as needing to be banned. There are multiple reasons for this. First of all, you may have selected a Tor exit node with policies which disallow Tor clients to access IRC through it. Thus, you must try with multiple exit nodes randomly selected from some listing of Tor exit nodes before despairing. If you have checked multiple hosts and your BOPM refuses to recognize them, you may have misconfigured your BOPM’s blacklist
entry. Double-check that you have put your correct server’s public IP in reverse order properly along with the correct port in the blacklist::name
entry. Test that BOPM’s DNS is working by looking up D.C.B.A.P.H.G.F.E.ip-port.exitlist.torproject.org
, perhaps using the getent hosts
or dig
tools. Remember to rehash BOPM (by /kill
ing it with your /oper
powers perhaps) after editing bopm.conf
.
Leave a Reply