Moving IP ranges
Urgent need to change from one ISP to the other. Don’t really want to speak of the reasons for this here. Anyway, since last night I’ve been working on this every waking hour that I could spare. Even put off commitments to a big customer to get this done with. Bad news: it’s still not done. I need to make this entry quick, but I don’t want to miss too much of what I’ve been doing.
My iptables rules are a leap forward for me compared to what I’ve been
doing. I think I might try and dumb down my iptables rules script
that I’m going to try using after I’ve (A) ironed out any bugs, and
(B) removed sensitive information, dumbed it down into an example,
etc. Things I’m doing that I’ve (stupidly) never done before: for
services, branch to a chain that lists all the hosts providing that
service when you match the service’s port; reorganizing rules based on
which has the most packets (iptables -nvL); when mucking with
iptables rules remotely, make a “safe host” entry at the top of the
the INPUT and FORWARD chains that contains an unqualified
ACCEPT for that IP address.
I also recompiled my kernel/iptables/wanpipe with the CONNMARK
patch.
Here’s the reason: I’ve got two Internet connections with different IP
ranges on them. I’ve got one internal network with reserved
addresses. To make an example, say an incoming SMTP connection comes
in on Internet connection B. Packet gets NAT’ed, sent through to SMTP
server. Now SMTP server makes a response to the client. When this
datagram hits the server, you have no way of determining whether the
packet should be sent out Internet connection A or Internet connection
B (where it belongs), except giving the SMTP server two IPs and
filtering on that perhaps. CONNMARK adds a field to the structures
already maintained by the conntrack code which is basically like
fwmark. You can match on this “connection mark” (connmark), copy
fwmark to the connmark, or copy the connmark to the fwmark. In my
case, when the SYN for the SMTP connection came in I’d set the
connmark on that connection. Then when any packet that has a connmark
is about to be routed (in the mangle table, PREROUTING chain)
I copy the connmark to the fwmark for any packets that have connmark
set. Once you’ve got fwmark set, you can route with ip rule based
on the fwmark. Nice.
Note on building this setup, though. I wanted an athlon kernel.
AFAIK, the only way to get source is to just rpmbuild -ba the spec
file with no explicit target. So I have to build twice: once with
rpmbuild -ba --target athlon kernel-2.4.spec, and once with
rpmbuild -ba kernel-2.4.spec. (I could do this all in one step
with --target i386,athlon I think — but I also noticed that
apparently rpmbuild -ba is building for i586, though the arch tag
on the resulting binary RPM is i386? Am I going insane here? This is
RH 8.0, too; isn’t that only supposed to support i686? If it had
built an i686 kernel and called it i386, maybe I’d buy it,
but… i586?)
Also, the CONNMARK patch wasn’t as simple as the MARK_operations
patch
I had applied earlier: it had a bunch of files, some of which weren’t
exactly in patch(1) format AFAIK. So I pointed KERNEL_DIR at a copy
of /usr/src/linux, had it patch that copy, then diff -urN
/usr/src/linux /my/usr/src/linux/copy > linux-2.4.18-CONNMARK.patch.
Fun. Put patch in spec file, rebuild kernel RPMs. This patch didn’t
modify iptables, either, which I found weird since I needed it to
build the CONNMARK target and connmark matcher. I later found out
that (at least when building from the RH 8.0 iptables 1.2.6a patch),
iptables will check /usr/src/linux for certain files corresponding to
the presence of the CONNMARK patch in the kernel; it will build this
target and matcher if it finds them. So: patch kernel source, install
kernel source, then build iptables.
Then, I broke the Internet when I rebooted. I realized that wanpipe
wouldn’t work when it was built for i386 and the kernel was built for
athlon. This didn’t see quite right to me, but the modules would give
me unresolved symbols. In the end, I ended up doing the same thing as
I did for the CONNMARK patch above: I let the wanpipe stuff patch a
copy of the kernel, diff‘ed the two, applied that patch, rebuilt
kernel RPM. Voila, now the modules that ship with the kernel are just
fine. I should split the modules out of my wanpipe RPM.
That was yesterday. Today I came up with a checklist of things that I have to do to hosts to bring them over to the new reserved IPs I’m switching to on the Internal network. I also added new iptables rules in preparation for the switch.
I ran into problems with DNS, though. I’ve got two weird DNS situations:
Hosts in our domain need to resolve to internal IPs when queried from the inside, and external IPs when queried from the outside.
At home I need some of the hosts from my primary domain name to resolve to internal IPs, and some to resolve the same as they would everywhere else. The rest of the hosts should resolve to one address regardless of where I’m querying them from.
So rather than hit an obvious solution (coming later) I went off on
tangents. I looked at a patch I had made to allow records like * NS
ns1.foo.com which actually works, but is applicable to (2) and not
really (1). Then I started reading on DNS and eventually hit some
random guy’s “Frequently Given
Answers” which had
some information on DJBDNS. I started looking in to it and decided I
should perhaps try DJBDNS. I actually started to like the idea of
synchronizing between master and slave(s) with ssh/rsync. I came to
accept the idea that I would run tinydns on one IP and dnscache on
another IP. OK. Then I realized it didn’t support RFC 2136 dynamic
updates like Bind 9. Then I read some more and really thought hard
about DJBDNS’ sort of lack of standards support. The only other thing
I can really think of that it doesn’t support is DNSSIG (or was it
DNSSEC? You know what I mean), which isn’t really done nor too useful
– especially if you listen to DJB and his advocates. (BTW, I
recommend reading a DJB vs. Bind thread or something similar on any
number of mailing lists like IETF’s namedroppers list for example.
His page on DJBDNS also has a bit about how he’s being oppressed by
the moderator for namedroppers, I believe it was.) I could probably
live without DNSSIG, at least for now, but dynamic updates? I really
like those. I also read about the extreme overhead some people had
for doing a make (rebuilding the CDB files, AFAIK) with large
numbers of records. They had much, much, much greater demands than I,
but I still thought about it. Now that I think about it, I doubt Bind
could keep up with some of their needs too.
Anyway, I ended up dropping DJBDNS. I considered running three views
in Bind 9: one for internal zones, one for external zones, and one for
“common” zones that needed to be queried from either of the first two
views with the same resolutions (RR’s, IP’s returned, whatever) for
both. I was going to have the server listen on port 54 in addition to
the usual ports. Then I would setup the internal and external views
to match based on the source, and set them up as forward only views.
They would answer queries for the few (two, I much later realized)
internal zones they had information for, but forward to localhost port
54 for any other queries. localhost:54 would be caught by the common
view. Voila, a union of sorts. One problem I thought of, though, was
CNAMEs: request comes in for www.customer.com, internal zone gets
query, doesn’t have authoritative information for it in this view and
so forwards to localhost:54, common view gets it, finds
www.customer.com. CNAME web1.ourdomain.com., goes to look up
web1.ourdomain.com. (Note: at this point I’m not sure I’m correct.
The name server might not try to look this up, but instead return the
CNAME with no other information back to the internal view. In this
case, the rest of this example is moot.) Now it tries to look up
ourdomain.com, which is a zone that has different addresses depending
on whether it’s queried internally or externally. However, if
localhost:54 tries to send a query to localhost:53, and the
internal/external zones match on source address of the query, which
view do they answer from for the address of www.customer.com?
Kaplooey, brokenness.
Then I somehow started thinking about DNS tools, and I kind of hit me:
hey, isn’t there an include statement. Sure enough, and it says it
basically just acts like the contents of the named file were inserted
into the configuration at that point. Bingo: create
internal-zones.conf, external-zones.conf, and
common-zones.conf. Two views that discriminate based on query
source, they both have all the zones that we’re authoritative for, and
I don’t have to manage two separate lists of zone statements in two
separate view statements. I haven’t tested this yet, but I suspect it
will work. The only odd thing about this might be my one dynamic
zone; I’m not sure if it’s going to reflect the changes to the zone in
both views if I simply point the zone statements at the same files.
I’m kind of worried about the journal I believe it makes. I’ll get
back to you later if this actually all works out.
I don’t actually feel like writing much about (2) right now. My
wildcard NS patch (which I’ll make available upon request; mail
me if you want it) fixes things up. My
home server is configured with this patch, and the real
primary/secondary for the domains are listed with * NS on my home
server. In this manner, my home server tries to match the record from
more specific records in the zone it has, but if it can’t find any
will just return the referral to my real primary/secondary servers.
In other news, I’m still without high-speed Internet access at home. ardent, euphorik and I have discussed using 802.11b to set up a secure link between our two apartments, and then euphorik and I will get DSL while ardent keeps his cable. In this way we’d hopefully never both be out of Internet access (unless we lost power or something) and can use the other person’s connection as a backup. Details to be finalized, and we’re not even sure if we can get the wireless link through the building — which is how it’s going to have to be, I think. I don’t think the apartment complex would much appreciate me extending an arm off my third story porch 10′-15′ to point an antenna at ardent’s porch.