NetworkConfiguration
The information on this page is a mixture between the household's network configuration, and sections on how to configure a Linux machine for various networking tasks. The reason for this is that for many years I was using a Linux machine located in the household itself to provide all networking services such as DHCP, NAT and firewalling. These days a Fritz Box ADSL router has taken over all network-related responsibilities in the household, and the Linux machine is now a dedicated server machine situated somewhere in the cloud.
Consequently some of the information on this page, such as configuring firewall and NAT rules with iptables
, is no longer in active use and may have become outdated. Also, the page should probably be split in two, but for the moment this is too much work.
In the page history there are older revisions of this page that show how the network was laid out and configured when the Linux machine still was in the household.
Household network layout
Physical network layout
+----------+ | Internet | +----------+ | | <-- WAN | +------------------+ | ADSL router | +------------------+ | | <-- LAN | +--------------+ | Switch | +--------------+ | | | +--------------------+ +------------------------------------------------- | Wi-Fi access point | | +--------------------+ | | | | | | +-------------------------+------------------+ +--------------------+---------------+ | | | | | | +---------------------+ +---------------------+ +-----+ +----------------+ +----------------+ +-----+ | Intranet computer 1 | | Intranet computer 2 | | ... | | Wi-Fi client 1 | | Wi-Fi client 2 | | ... | +---------------------+ +---------------------+ +-----+ +----------------+ +----------------+ +-----+
Notes:
- This current layout is acceptable only because the ADSL router is equipped with firewalling capabilities. In a very old configuration the household was connected to the Internet via a pretty stupid cable modem, which was basically a bridge that translated between different physical network system types (xDSL, Ethernet), but nothing else. With such a device, the layout above would leave the LAN side wide open to any intruders.
- Ten flawless firewalls with superb configurations are still powerless if the enemy comes from within the protected network: An intranet machine may have been infected by a virus or some other bit of malicious software (trojan, spybot, whatever) because the user has been carelessly opening email attachments or visiting infected websites. The best protection against this threat is a wary and knowledgable user! Supporting roles may be filled with server and/or desktop virus scanners and desktop firewalls monitoring outgoing connections (e.g. Little Snitch on Mac OS X, ZoneAlarm on Windows).
Logical network layout
In this diagram I have added network addresses and removed boxes that referred to hubs and/or switches. Only the most important routers and gateways have been left to illustrate the network boundaries.
+----------+ | Internet | +----------+ | | | +------------------+ | ADSL router | +------------------+ | 192.168.178.0 | | | +--------------------+ +------------------------------------------------- | Wi-Fi access point | | +--------------------+ | | | | | | +-------------------------+------------------+ +--------------------+---------------+ | | | | | | +---------------------+ +---------------------+ +-----+ +----------------+ +----------------+ +-----+ | Intranet computer 1 | | Intranet computer 2 | | ... | | Wi-Fi client 1 | | Wi-Fi client 2 | | ... | +---------------------+ +---------------------+ +-----+ +----------------+ +----------------+ +-----+
Notes:
- The Wi-Fi access point is configured as a bridge, it does not create its own network
xDSL configuration
See the DSL page.
WiFi router configuration
Currently my WiFi router is an Airport Extreme base station. Details about its configuration can be found on the WiFi page.
Kernel and modules
Basic networking support
If you build your own kernel, you will have to enable some things in the kernel configuration sub-menu /kernel/device drivers/networking support:
- Set network device support = YES
- Choose the ethernet sub-menus that contain the device drivers for your network cards, then enable the device drivers either as a module or compiled directly into the kernel
- Compile the new kernel & reboot
- If you configured the device drivers as a module, you should use "modconf" to make sure that the modules have been loaded and are available for the following configuration
- I did not choose the module option because networking is an integral part of the system I intend to build
netfilter/iptables
Kernel configuration options required for iptables are located in the kernel configuration hierarchy under "Networking->Networking options->Networking packet filtering framework (Netfilter)". Most important for iptables and NAT are the connection tracking options.
It seems as if netfilter options can be built as modules only. On the running system, available modules can be found in
/lib/modules/2.6.38-2-686/kernel/net/ipv4/netfilter/
Kernel modules can be managed interactively through the modconf utility, or on the command line via insmod, rmmod and lsmod.
Note: If the modules should be unloaded, any rules that are currently active must be removed first.
Interface names
Over the years there have been several changes to the way how network interfaces are named. This page on the Debian wiki has a nice summary. The page also shows how to migrate from the old "persistent names" scheme to the most recent "predictable names" scheme. I did this migration while I was still on Debian 9 ("stretch"), shortly before I upgraded to Debian 10 ("buster").
This command lists all network interfaces that are currently configured for your system:
ls -l /sys/class/net
The default is for systemd
(or is it still the udev
subsystem?) to assign a predictable name to a network interface. It does this based on the content of
/lib/systemd/network/99-default.link
This default can be overridden, though, and that is what I am doing, because I have a somewhat unhealthy distrust of systemd
getting it right. Also I prefer simple and clean names to gibberish names that no one can remember. So how does this work? You simply have to place a file into /etc/systemd/network
with a name that is lexically placed before the default file 99-default.link
. So here's what I have:
root@pelargir:~# cat /etc/systemd/network/10-persistent-net-internet0.link [Match] MACAddress=40:a8:f0:75:71:bc [Link] Name=internet0 root@pelargir:~# cat /etc/systemd/network/10-persistent-net-internet1.link [Match] MACAddress=40:a8:f0:75:71:bd [Link] Name=internet1
Notes:
- Read
man systemd.link
for details about the config file format. - Because of the MAC matching I need a separate file for naming each network interface.
- The Debian wiki page mentions that we should (must?) not use "eth0" or any other name that the kernel might use for another interface.
- Matching to a fixed MAC might not always be possible. Consult the history of this wiki page to find an
udev
config example where I had to cope with a MAC address that was randomly generated on every reboot.
The following command will show you how systemd
(or udev
) would name the network interface:
root@pelargir:~# udevadm test-builtin net_id /sys/class/net/internet0 2>/dev/null ID_NET_NAME_MAC=enx40a8f07571bc ID_OUI_FROM_DATABASE=Hewlett Packard ID_NET_NAME_ONBOARD=eno1 ID_NET_LABEL_ONBOARD=enNIC Port 1 ID_NET_NAME_PATH=enp3s0f0
Notes:
- Only the lines starting with
ID_NET_NAME_
matter - The system takes the line whose key has the highest priority. List of key priorities, highest to lowest:
- ID_NET_NAME_FROM_DATABASE
- ID_NET_NAME_ONBOARD
- ID_NET_NAME_SLOT
- ID_NET_NAME_PATH
- ID_NET_NAME_MAC
- So in the example above, the interface network name that the system would choose had I not overridden it would be "eno1".
Interface configuration
General
This file contains the network interfaces and their configuration:
/etc/network/interfaces
Some or all interfaces may already be present if you have configured them during the initial system setup (e.g. "base-config"). Otherwise you will have to add them manually now.
man interfaces
gives useful information about the options that you can tweak. Basically the following rules apply:
- The definition of a TCP/IP interface always starts with the line "iface eth<xxx> inet". Note that the interface name is merely a reference; the name definition has happened somewhere else in the udev subsystem
- On the same line you add a word that determines how the interface gets its characteristics (e.g. IP address)
- The word "dhcp" is used if the interface is configured by a DHCP server; this usually concludes the interface definition
- The word "static" is used if you want to statically configure the interface in the interfaces file; you have to add a few more lines in this case
- A line that defines the IP address: "address <ip address>"
- A line that defines the netmask: "netmask <netmask>"
- There should be a line "auto eth<xxx>" for every network interface that should be automatically brought up when the system is booting
If you need to know more, you should read the man page mentioned above. Here is an example how my configuration in /etc/network/interfaces looks like:
# The loopback network interface auto lo iface lo inet loopback # Integrated gigabit ethernet controller: 34:15:9e:2e:ca:38 # The Intranet interface for wired connections auto eth0 iface eth0 inet static address 192.168.1.11 netmask 255.255.255.0 # Fast ethernet-over-USB controller: 00:24:32:01:a7:83 # The Internet uplink auto eth1 iface eth1 inet dhcp # Gigabit ethernet-over-USB controller: 00:12:17:f2:34:05 # The Intranet interface for wireless connections auto eth2 iface eth2 inet static address 192.168.2.6 netmask 255.255.255.0
DHCP
Even though the Linux server runs its own DHCP server, the eth0
interface must still be statically set up. If it were configured via DHCP, there would be potential timing problems because the DHCP server comes up rather late in the boot process, and other services may already need the proper IP address on eth0
(e.g. slapd
).
Command line utilities
This command prints out the currently defined interfaces, and their status:
ifconfig
These commands manually start or stop interfaces:
ifup eth<xxx> ifdown eth<xxx>
To renew a DHCP lease, first issue an ifdown command, followed by an ifup command.
Note: I am not entirely sure about the consequences, but possibly the command dhclient eth1 could also be used to renew a DHCP lease on a specific interface (eth1 in the example). When no interface is specified, the command renews the leases on all interfaces. Use with caution!
iptables
Before I go into more details about concrete network configuration, here is a short chapter about the general concepts and usage of the iptables software package.
Documentation:
- http://www.netfilter.org/
- http://www.netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html
- http://www.netfilter.org/documentation/HOWTO//NAT-HOWTO.html
iptables implements a kernel-level packet filter. Basically, you can do everything you like with iptables:
- Routing
- NAT
- Firewall rules
- Arbitrary security rules and other stuff
This section provides information condensed from the excellent iptables man page. The section is probably not useful if you do not have a basic understanding of how iptables works.
Overview
Every IP packet that arrives in the Linux kernel is fed into iptables. iptables is configured with a number of rules. Each rule can match a set of packets. Each rule specifies what to do with a packet that matches.
Rules are organized in two levels:
- tables
- chains
Tables
The following tables exist:
- filter = the default table
- nat = rules in this table are consulted first when a packet that creates a new connection is encountered
- mangle = this table is used for specialized packet alteration.
- raw = not considered here
Chains
Every table contains a number of pre-defined chains. A table may also contain user-defined chains.
The filter table has the following pre-defined chains:
- INPUT: for packets that come in from outside and have the host as their target
- FORWARD: for packets that come in from outside and that the host is supposed to route to a target != the host
- Note: if IP forwarding is disabled, or if the kernel does not know how to route a packet, the packet is discarded before it is given to iptables (= it never arrives in the FORWARD chain)
- OUTPUT: for packets that are generated on the host
The nat table has the following pre-defined chains:
- PREROUTING: for altering packets that come in from outside and that the host is supposed to route to a target != the host
- OUTPUT: for altering packets that are generated on the host, before the packets leave the host
- POSTROUTING: for altering packets as they are about to leave the host (packet source does not matter!)
The mangle table has the following pre-defined chains:
- INPUT: see filter/INPUT; only available since kernel 2.4.18
- FORWARD: see filter/FORWARD; only available since kernel 2.4.18
- PREROUTING: see nat/PREROUTING
- POSTROUTING: see nat/POSTROUTING; only available since kernel 2.4.18
- OUTPUT: see filter/OUTPUT
Schematic overview
The following schematic provides an overview of the existing tables/chains and the flow of a packet:
+--Host---------------------------------------------------------------------------------------------------+ | | IN | +-----------------------+ +-----------------------+ | OUT ---------> | PREROUTING (chain) | | POSTROUTING (chain) | ---------------> | | mangle + nat (tables) | | mangle + nat (tables) | | | +-----------------------+ +-----------------------+ | | | | | ^ | | | | | | v | | | | | | ^ | | | / \ | | | / \ +--------------------------+ | | | routing? ---------> | FORWARD (chain) | --------------> | | | \ / | filter + mangle (tables) | | | | \ / +--------------------------+ | | | v | | | | | | | | | | | | | | v | | | | | +--------------------------+ +---------------+ +--------------------------------+ | | | INPUT (chain) | ---> | local process | ---> | OUTPUT (chain) | | | | filter + mangle (tables) | +---------------+ | filter + mangle + nat (tables) | | | +--------------------------+ +--------------------------------+ | | | +---------------------------------------------------------------------------------------------------------+
Rules / Policy
Every chain consists of a number of rules (may be 0). Every built-in chain also has a policy:
- A policy is a kind of default target (see below)
- The policy is applied if none of the chain's rules match
- The target defined by a policy cannot be another chain
Every rule consists of a number of "selection criteria" that determine whether or not a packet is matched by the rule. If a match occurs the rule is further consulted for a "statement" about what should happen to the packet.
- The "statement" (not the "selection criteria!) is called a "target"
- If the "selection criteria" does not match a packet, the next rule in the chain is consulted
- If the "selection criteria" matches a packet, the target determines the next rule that should be consulted; the following is a short overview of the most common and important targets
- The target can be a "jump" to a user-defined chain in the same table
- The target ACCEPT accepts the packet
- The target DROP completely drops the packet
- The target QUEUE passes the packet to userspace (not covered in this document)
- The target RETURN goes back to the "calling" chain
- Exception: if the current chain is a built-in chain, the target RETURN uses the the target defined by the chain's policy
- Many more targets are possible; often targets depend on the table or chain that the rule is located in
- If a packet is not matched by any rule in a built-in chain, the target defined by the chain's policy is used
Syntax
This chapter provides a few useful examples for copy-paste.
List the rules in all chains in the table filter, without trying to resolve host names:
iptables -t filter -L -n iptables -L -n
List the rules in the chain PREROUTING in the table nat, without trying to resolve host names:
iptables -t nat -L PREROUTING -n
List the rules in all chains in the table mangle, including rule numbers:
iptables -t mangle -n --line-numbers
Insert (-I) a rule at position 666 into the chain INPUT in the table filter. The rule is: DROP all packets from source 1.2.3.4/24 to destination 5.6.7.8/24.
iptables -t filter -I INPUT 666 -s 1.2.3.4/24 -d 5.6.7.8/24 -j DROP
Delete a rule in table filter:
iptables -t filter -D <all options used when the rule was added with -A or -I>
Append a rule to the chain FORWARD in the table filter:
iptables -A FORWARD ...
Useful examples
Log TCP packets coming in to this host with destination port 1234:
iptables -t filter -A INPUT -p tcp --dport 1234 -j LOG --log-prefix "foobar: "
Log TCP packets coming in to this host via interface eth42:
iptables -t filter -A INPUT -i eth42 -j LOG --log-prefix "eth42 input: "
Modules
Behind the scenes iptables
is organized as a collection of Linux kernel modules under the common name "netfilter". The man page describes many of these modules, but if you need to be sure if a certain module is available on your system, have a look at the content of the folder
/lib/modules/2.6.38-2-686/kernel/net/ipv4/netfilter/
Routing
IP Forwarding
By default, a Linux box will not route IP packets from one IP network to the other. To enable routing, you have to edit
/etc/sysctl.conf
(/etc/network/options is deprecated), and add the line
net.ipv4.ip_forward=1
To activate the changes in sysctl.conf, run the command
sysctl -p
(sysctl is used to change kernel parameters at runtime). From now on, /etc/init.d/networking will turn on routing whenever it is run (e.g. during a system boot). It is also possible to enable or disable routing on the fly, by issuing one of the following commands:
echo 0 >/proc/sys/net/ipv4/ip_forward echo 1 >/proc/sys/net/ipv4/ip_forward
Now that we have basically enabled routing, we also have to define HOW routing should be done.
Basic routing
Basic routing is done via the IP routing table (or via entries in iptables, but this is not covered in this document). The command
route
is used to display the current entries in the table. An alternative is
netstat -rn
Example output on my machine:
pelargir:~# netstat -rn Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 192.168.178.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth2 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 0.0.0.0 192.168.178.1 0.0.0.0 UG 0 0 0 eth1
I have already mentioned in the previous chapter about the physical network layout that eth1 is the interface that connects to the outside world. This is the reason why the default route (destination 0.0.0.0) points to that interface.
Automatic updates to the routing table
When ifup brings up a network interface that is configured to use DHCP, entries to the routing table are automatically created from the information provided by the DHCP server. If the DHCP server defines a gateway (router) 192.168.178.1 and a subnet mask of 255.255.255.0, the entries to the routing table might look like this:
Destination Gateway Genmask Flags MSS Window irtt Iface 192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 0.0.0.0 192.168.178.1 0.0.0.0 UG 0 0 0 eth1
On a system that has more than one interface configured to use DHCP, care must be taken in the DHCP configuration that ifup does not add multiple default routes to the routing table. See the DHCP page for more details.
Manual updates to the routing table (static routing)
To add/remove entries to/from the routing table, you use the route command with the add or del option. For instance:
route add -net 192.168.178.0 netmask 255.255.255.0 dev eth1 route add -net 192.168.1.0 netmask 255.255.255.0 dev eth0 route add -net 192.168.2.0 netmask 255.255.255.0 dev eth2
To manually add a default route (i.e. a route that covers all traffic for which there is not a specific network route):
route add default gw 192.168.178.1
In the default route example no device/interface was specified. In this case the kernel tries to determine the correct device/interface by examining already existing routes.
NAT
Network-address translation (NAT) can be enabled using a single iptables rule. For better understanding you may have to read the general chapter above about iptables.
iptables -t nat -A POSTROUTING -o <outgoing interface> -j MASQUERADE
Dissemination of the rule:
- -t nat = we want to add a rule to the nat table, i.e. we want to manipulate packets using NAT
- -A POSTROUTING = we manipulate only after the routing target has been determined
- -o <outgoing interface> = we manipulate only packets that are going to leave the host on the given interface
- -j MASQUERADE = we want to manipulate the packet so that the source address is changed to be the address of <outgoing interface>
The iptables man page says that the MASQUERADE target should be used with dynamically assigned IP (dialup) connections. If a static IP is present, the man page recommends usage of the SNAT target. I have not investigated the reason for this, but the appropriate rule would look like this:
iptables -t nat -A POSTROUTING -o <outgoing interface> -j SNAT --to-source <ip adress of outgoing interface>
Note: I no longer use NAT on my Linux box because NAT services are now provided by my xDSL router.
DNS
Overview
Once we go beyond the pure realm of IP addresses we come to the humanly tainted realm of domain and host names. This starts with the hostname of the system and progresses via the domain name that the system is in towards the full domain name system (DNS) of the Internet.
This section provides the essentials and pointers to other pages in this wiki with more information.
For information about configuration of a DNS server, see the BIND page on this wiki.
Hostname
The system's current hostname can be queried by invoking the hostname command without parameters.
While the system is running, its hostname is set by invoking the hostname command with the desired name:
hostname pelargir
Note: The hostname is set purely in memory, no file is changed by this command.
When the system is booting, a startup script reads the hostname from the file /etc/hostname and sets it by invoking hostname.
To permanently change the system's hostname even across a reboot:
- Invoke the command hostname to change the hostname while the system is running
- Modify /etc/hostname to make sure that the same name is used when the system reboots the next time
Domain name and FQDN
The FQDN (fully qualified domain name) of the system is determined by concatenating the system's hostname and the system's domain name.
To query the system's current domain name:
hostname --domain
To query the system's FQDN:
hostname --fqdn
The question remains: How do these utilities determine the system's domain name? The answer (from the man page of hostname): They ask the so-called resolver. From the man page (man hostname):
The FQDN of the system is the name that the resolver(3) returns for the host name. Technically: The FQDN is the name gethostbyname(2) returns for the host name returned by gethostname(2). The DNS domain name is the part after the first dot.
Read the next section for the ongoing discussion of the topic.
The resolver
What is the resolver? From the man page (man resolver):
The resolver is a set of routines in the C library that provide access to the Internet Domain Name System (DNS).
The resolver man page mainly talks about its configuration file /etc/resolv.conf which is used when the resolver talks to a DNS server. We come to this in a moment. What is also important (and what the resolver man page does not tell us) is that the resolver may have other sources of information besides DNS servers: For instance, the /etc/hosts file, or an LDAP server. Also important is that one can influence the order in which the resolver queries these sources. The mechanism involved is called "Name Service Switch" (NSS) and the configuration file involved is
/etc/nsswitch.conf
Notes
- The hostname man page mentions another resolver configuration file /etc/host.conf. This is misleading, that file is no longer used by modern Linux systems. As the "Resolver library" section in this interesting FAQ explains: "The older Linux standard library, libc, used /etc/host.conf as its master configuration file, but Version 2 of the GNU standard library, glibc, uses /etc/nsswitch.conf."
- For more information on my use of NSS, see the NSS page on this wiki
On my system, the relevant entry in /etc/nsswitch.conf is this:
hosts: files dns ldap
Before we try to solve the mystery of how the system's FQDN is determined, we have a quick look at /etc/resolv.conf. The resolver man page tells us that in that file the "domain" configuration option refers to the "local domain name". A further quote:
Most queries for names within this domain can use short names relative to the local domain. If no domain entry is present, the domain is determined from the local hostname returned by gethostname(2); the domain part is taken to be everything after the first '.'.
For instance, on my system /etc/resolv.conf looks like this:
domain dmz.herzbube.ch search dmz.herzbube.ch nameserver 192.168.1.6 nameserver 212.101.0.10
The file is automatically generated when the system acquires a DHCP lease and the DHCP server hands out various information such as the domain and the name servers. On a system that does not use DHCP, /etc/resolv.conf must be edited by hand.
The mystery of the FQDN
From what we have learned by now, we can construct the following sequence of events:
- User issues the command hostname --fqdn
- hostname makes system call gethostname(); result is "pelargir"
- hostname makes system call gethostbyname; triggers the resolver and returns the result
- resolver performs lookups in the order defined by /etc/nsswitch.conf; as we have seen, on my system this is "files dns ldap"
- resolver looks in /etc/hosts and finds nothing for "pelargir" (/etc/hosts contains only one entry that maps 127.0.0.1 to "localhost")
- resolver queries the DNS server; because "pelargir" is not a FQDN the resolver uses the "local domain name" defined in /etc/resolv.conf for completion; the actual query to the DNS server therefore is "pelargir.dmz.herzbube.ch"
- the DNS server, of course, knows the name and returns a result to the resolver, which in turn returns the FQDN to hostname
Note: We have ignored nscd in our discussion because on my system this caching daemon is currently set not to cache host lookup information.
Why is the FQDN important?
All kinds of programs need this information, it is just part of a properly configured system.
At one time, when I tried to remove "pelargir" from /etc/hosts but hadn't set up my own DNS server yet, I ran into trouble because slapd couldn't be started anymore. Also hostname would completely block. The reason for this was that NSS was configured with "ldap" as the last lookup source, so when slapd or hostname made the lookup, NSS couldn't find the hostname in /etc/hosts, nor in any of the (at that time external) DNS servers, so it tried to contact the LDAP server which was either down, or not properly configured for host lookups. Certainly this was misconfiguration on my part, but it just shows that a lot of tools require not only a hostname but rely also on a properly configured FQDN.
Note: One incorrect solution I have found on the Internet was to place the FQDN directly into /etc/hostname. This is completely wrong, as it would result in the hostname to be set to something that resembles a FQDN.
FQDN without a DNS server
Without a DNS server, the FQDN would have to be defined in /etc/hosts. The FQDN would be the first parameter, with optional abbreviations and aliases as the following parameters. For instance:
127.0.0.1 localhost 192.168.178.20 pelargir.dmz.herzbube.ch pelargir
List hostname in /etc/hosts
Although this is not strictly necessary if DNS is up and running, it might still be a good idea to add the system's hostname to /etc/hosts
. For instance
127.0.0.1 localhost pelargir
- This entry might save the day if DNS is down for any reason
- The entry might also help if a service makes trouble for some network-oriented reason (e.g. for some strange reason Exim 4.76 has problems and hangs when 1) it gets an invalid HELO host name that cannot be resolved, and 2) it also cannot find the local hostname in
/etc/hosts
(a running DNS server that is capable of providing the FQDN appears to be insufficient))
The problem with the entry above is that it sets the FQDN to "localhost". This is not really a FQDN, and a few software packages (e.g. Apache) do not like that. So in the end, to make all parties happy, I have decided to put the following line in /etc/hosts
:
192.168.178.20 pelargir.dmz.herzbube.ch pelargir
Packet mangling with iptables
Avoid routing local traffic to ADSL router
The problem
Regular access to one of the public hostnames (e.g. www.herzbube.ch) comes in from the WAN side. In this case the Router correctly routes traffic to the Linux server, which can then serve the request properly.
Unfortunately the same happens when I try to access a public hostname from within the LAN: Traffic is first routed to the ADSL router, which then re-routes everything to the Linux server. The result is reduced LAN speed (in some cases the reduction is quite dramatic!) because packets need to travel 3 network segments instead of just 1 (or 6 for the roundtrip, instead of just 2).
The reason for this behaviour is that public hostnames always resolve to my public IP address, and that address is occupied by the ADSL router.
The solution that does not work
The correct solution for this problem would be, of course, to set up a proper DNS configuration, in which names such as www.herzbube.ch would resolve to a local IP address when the DNS request comes in from the LAN.
Unfortunately this is not possible because the domain name registrar for the TLD ch (Switch) does not accept arbitrary DNS servers for delegation, which means I am forbidden to deploy my own primary DNS server for herzbube.ch. I am therefore stuck with using a public DNS server (currently dyn.org) as primary DNS server for herzbube.ch, and that public server is, of course, incapable of resolving to LAN IP addresses.
iptables to the rescue
A solution with iptables is this: whenever traffic is routed from the Linux server to the static IP 212.101.18.224 (= the ADSL router), iptables must make sure that the traffic is not actually delivered to the ADSL router, but is instead mangled so that the destination interface is 192.168.178.20 (eth1).
The rule looks like this:
iptables -t nat -A PREROUTING -s 192.168.0.0/16 -d 212.101.18.224/32 -j DNAT --to-destination 192.168.178.20
Dissemination of the rule:
- We use NAT so that the client has no clue that we are mangling
- Unlike the "regular" NATting where the source address is mangled (SNAT), we mangle the destination address (-j DNAT)
- Mangling happens before routing (-A PREROUTING)
- Mangling occurs for all packets that have their origin in the 192.168.0.0 network (= the LAN, including all subnets)
- If the LAN has more networks, the -s option would have to include those, too
- An alternative might be to specify an incoming interface, e.g. -i eth0
The rule above uses the PREROUTING chain, which means that the rule affects only packets that come in from outside and that the Linux server is supposed to route. We need another rule that affects packets that are generated on the Linux server itself. That rule uses the OUTPUT chain and looks like this:
iptables -t nat -A OUTPUT -d 212.101.18.224/32 -j DNAT --to-destination 192.168.178.20
Dissemination of the rule:
- The basic elements are the same as in the first rule
- We can leave out the -s option because using the OUTPUT chain already restricts the rule to packets originating on the Linux server
In order to activate the rules on a server reboot, the iptables command is added to one of the init scripts in /etc/init.d/S99<foo>.
Route file sharing traffic to dedicated host
When a client on the LAN side starts a file sharing application (e.g. for the BitTorrent or the eDonkey file sharing networks), the client typically needs to be accessible from the outside of the LAN on certain ports. These file sharing ports are always located in the port range >= 1000.
One solution is to modify the ADSL router's port forwarding rules (Menu 15.2.1 "NAT Setup -> NAT Server Sets -> Server Set 1 (Used for SUA only)") so that traffic on the required ports is directly forwarded to the IP address of the client that runs the file sharing application(s).
The problem with this is that the router supports only a limited number of slots for defining port forwarding rules (12 slots in my case). I prefer to use these slots for defining exceptions to the "block all ports under 1000" rule. Since all traffic on ports >= 1000 (i.e. file sharing ports are included by this) is already routed to the Linux server, it is therefore easier to define an iptables rule that forwards file sharing traffic to the correct client.
The rule looks like this:
iptables -t nat -A PREROUTING -p tcp -i eth1 -d 192.168.178.20/32 --dports 50116 -j DNAT --to-destination 192.168.1.9
Dissemination of the rule:
- We use NAT so that the routing occurs transparently, i.e. the file sharing application will think that the Linux server generated the request (it sees the Linux server's IP address as the source IP address)
- Unlike the "regular" NATting where the source address is mangled (SNAT), we mangle the destination address (-j DNAT)
- Mangling happens before routing (-A PREROUTING)
- Mangling occurs for all packets that come in on the eth1 interface, i.e. that have their origin on the Internet
- Note: it is easier to use -i to match all Internet traffic than to use -s (which would require to specify a source IP address)
- -p tcp is required so that a port can be specified (the IP protocol has no ports)
- Last but not least, --dport is used to specify the port
- If multiple ports need to be specified and the port numbers are not consecutive (i.e. cannot be expressed as a port range), the multiports module (loadable by the -m option if the kernel module exists) provides the --dports option
The following file sharing ports are known:
- BitTorrent
- Azureus
- Determines a random port number when the application is launched for the first time
- I always use 50116
- Default Ports
- TCP 6881-6889
- Azureus
- eDonkey2000 (eD2k)
- aMule
- Uses default ports
- Default Ports
- TCP 4662 (to get an eD2k HighID)
- UDP 4665 (always TCP port +3)
- UDP 4672
- aMule
- Gnutella
- Phex
- Determines a random port number when the application is launched for the first time
- I always use 5381
- Default Ports
- TCP + UDP 6346
- Phex
IPX/SPX and NCP
Purpose
At one time at my workplace it looked as if I would have to configure a Linux machine to connect to the corporate Novell network. The following chapters document the research I did on this topic. The information presented here is probably not complete because I abandoned the effort after it became clear that a network connection would be feasible through TCP/IP after all. I leave these chapters to stand as they are in case I will have to follow-up on the issue at a later time.
Overview
(partly quoted from the Wikipedia articles)
IPX/SPX is a networking protocol used by the Novell NetWare operating systems. IPX is comparable to IP because it is responsible for end to end (source to destination) packet delivery. SPX is comparable to TCP because it sits on top of IPX and provides connection-oriented services between two nodes on the network.
NCP (the NetWare Core Protocol) is used to access file, print and other network service functions. TCP/IP and IPX/SPX are the supported underlying protocols.
On Linux
The IPX/SPX protocol is available as a Linux kernel module. On Debian, the ipx package provides utilities to configure the IPX network.
NCP server services can be provided through the MARS_NWE NetWare emulator (http://www.compu-art.de/mars_nwe/).
An NCP client implementation is available through the Debian ncpfs package.
References
http://www.linuxjournal.com/article/1354 http://www.faqs.org/docs/linux_network/x-087-2-ipx.ncpfs.client.html http://tldp.org/HOWTO/IPX-HOWTO.html http://download.novell.com/Download?buildid=yI3iQFO4Nes
ipx_* utilities
The Wikipedia article about IPX has the following to say about "IPX addressing":
- Logical networks are assigned a unique 32-bit hexadecimal address in the range of 0x1 - 0xFFFFFFFE.
- Hosts have a 48-bit node address which by default is set to the network interface card's MAC address. The node address is appended to the network address to create a unique identifier for the host on the network.
The Wikipedia article also lists 4 encapsulation types of "IPX over Ethernet"
- 802.3 (raw)
- 802.2 (Novell)
- 802.2 (SNAP)
- Ethernet II
From this information, and the name of the available ipx_* utilities, I deduce that an IPX network needs to be set up as detailed in the following chapters.
IPX network interface
First an IPX network interface needs to be set up with ipx_interface. If for instance IPX traffic uses the ethernet interface eth0, we can define the IPX interface like this:
ipx_interface add eth0 802.2 0
According to the man page for ipx_interface:
- 802.2 is a valid frame type; I don't know whether 802.2 (Novell) or 802.2 (SNAP) will be used
- by specifying an invalid frame type "foobar", we can fool ipx_interface into printing out a help text that informs us that the following frame types are valid
- 802.2
- 802.2TR
- 802.3
- SNAP
- EtherII
- so we still don't know that exactly 802.2 is, but we assume that it's the reasonable sounding "Novell" variant
- by specifying an invalid frame type "foobar", we can fool ipx_interface into printing out a help text that informs us that the following frame types are valid
- a network number "0" is the same as not specifying a network number at all; the effect is that the network number will be detected automatically from the traffic on the network
Note: There is also an option to specify a primary interface. I don't know what this is, so I don't care...
As an alternative to all this stuff above, it might also be feasible to let IPX configure itself automatically. It does not do so by default, so we have to instruct it:
ipx_configure --auto_interface=on or ipx_configure --auto_primary=on [auto-select a primary interface]
IPX routing
ipx_route add target_network router_network router_node
ncp* utilities
The man page for ncpmount says
- on IPX: "You must configure the IPX subsystem before ncpmount will work. It is especially important that there is a route to the internal network of your server."
- on IP: "You must specify both -S logical_name and -A dns_name. logical_name is used for searching .nwclient, other configuration files and is logged into /etc/mtab, dns_name is used for connecting to server."
ncpmount provides a huge number of options that can be used for mountint a NetWare volume.
Worth investigating:
- mount option "tcp" = use TCP for connection to server
- -A dns name (mount option ipserver=dns name): When you are mounting volumes from NetWare 5 server over UDP, you must specify dns name of server here and logical server name in -S (or in server=). This name is used to switch ncpmount into UDP mode and to specify server to connect. Currently, DNS is only supported IP name resolution protocol. There is currently no support for SLP.
- -b (mount option bindery): If you are connecting to NetWare 4 or NetWare 5 through bindery emulation instead of NDS, you must specify this option.
- -i level (mount option signature=level): Enables packet signing. level is from 0 to 3: 0 means disable, 1 means sign if server needs it, 2 means sign if server allows it and 3 means sign packets always.
Mount all volumes (becauses no -V passed) from a server:
ncpmount -S <server> -U <user> -P <pwd> /mnt/<mount point>