My-Tiny.Net :: Networking with Virtual Machines



TCP/IP Level Access Controls



Earlier we finished configuration of stunnel, to provide encrypted communications. Here we look at lower-level access controls. The essential difference is that with SSL/TLS authentication credentials are provided voluntarily; with iptables and tcpwrap access is controlled using information in the IP and TCP packets that arrive at the server.

The term "firewall" describes filters operating at the network and transport layers that rely on packet headers to supply the attributes used to make access control decisions. Access control decisions are made using the one or more of the subject/object address, service, and direction of each individual packet.

At the very foundation of a firewall is a simple rule that reflects the system administrator's philosophy:
  • What is not allowed is denied
    or
  • What is not denied is allowed
Which one to adopt depends on the services and data you need to protect. It is perfectly reasonable to apply one philosophy to one set of servers and the other philosophy to another set of servers. To deny specific types of packets and accept all else requires a thorough understanding of specific security threats, and can be hard to implement. To accept specific types of packets and deny all else means you do not have to predict future attacks, but you must have a thorough understanding of network requirements

Here we will take a look at two firewall tools: iptables and tcpwrap. Either or both can be used to enforce the chosen philosophy.


RHEL 9 Resource Guide Fig. 15-1


Basic Concepts

A packet filter is an application configured to accept or reject packets, based on any observable characteristic of each packet, such as source and destination IP address, source and destination TCP port, packet type, sequence, etc..

Restrictions are specified in Access Control Lists (ACLs). ACLs can be implemented in a router as well as a separate server

Stateful firewalls specify "circuit-level" rules pertaining to connections rather than individual packets

There is a good explanation of IP filtering terms and expressions at
http://security.maruhn.com/iptables-tutorial/x2940.html

Packet Filtering: iptables

We can use iptables rules to configure tables of packet-filter rules in the Linux kernel - "in the kernel" meaning before any "user space" applications like tcpwrap or SSL/TLS.

The iptables framework is:
  • Each table has a number of chains
  • Each chain consists of a list of rules
  • Each rule specifies what to do with a matching packet
The default table (filter, ACL) has 3 built-in chains:
INPUT    controls traffic from outside the LAN
OUTPUT    places restrictions on outbound connections
FORWARD    allows control over routing between interfaces
IPTables uses policies (-P) to create default rules.
These rules will block all traffic on a network gateway:
iptables -P INPUT DENY
iptables -P OUTPUT REJECT
iptables -P FORWARD REJECT
DROP and DENY silently drop packets, REJECT returns a "connection refused" error to users.

Specific rules are appended (-A) at the end of an existing ruleset. -A is followed by the name of the chain for a rule, and flags to specify packet characteristics like like (p)rotocol, (i)nterface, (s)ource, (d)estination. The rule normally ends with an instruction to "jump to" (-j) a target. The targets ACCEPT, DROP, and REJECT behave as you would expect, while the LOG target can be used to log packets and let them continue moving through the chain. The target can also be another chain - for good examples, skip down to the custom chains section at http://www.pettingers.org/code/firewall.html

Some examples of rules: (for details see the Quick Reference :: iptables page on the menu)
# refuse telnet connections
  iptables -A INPUT -p tcp --sport telnet -j REJECT
  iptables -A INPUT -p udp --sport telnet -j REJECT

# allow ssh connections
  iptables -A INPUT -p tcp --sport 22 -j ACCEPT
  iptables -A INPUT -p udp --sport 22 -j ACCEPT

# Allow new TCP connections from hosts in the 192.168.1.0/24 network to port 137 (stateful)
  iptables -A INPUT -m state --state NEW -m tcp -p tcp -s 192.168.1.0/24 --dport 137 -j ACCEPT
Note how s! is used in the examples below. The first two rules drop all packets where the source IP address is not on the subnet specified, while the next two rules allow a specific IP address.

# allow connections to the portmap service (listening on port 111) 
# from the 192.168.0/24 network and from localhost 
# Any other port 111 packets are dropped.
  iptables -A INPUT -p tcp -s! 192.168.0.0/24 --dport 111 -j DROP
  iptables -A INPUT -p udp -s! 192.168.0.0/24 --dport 111 -j DROP
  iptables -A INPUT -p tcp -s  127.0.0.1 --dport 111 -j ACCEPT
  iptables -A INPUT -p udp -s  127.0.0.1 --dport 111 -j ACCEPT
But Hey - there is something very wrong with that list! The ACL rules are processed as a list from top to bottom, and as soon as a packet matches a rule the processing "jumps" to the -j target. In the example above the localhost rules will never be matched because the packet will be DROPped by the "source address is not" rules that come before.

The iptables ACL is usually in a shell script executed at boot time.

iptables Logging

The LOG target has options to tell iptables and syslog which log level to use. Normally there are eight log levels, or priorities as they are normally referred to: debug, info, notice, warning, err, crit, alert, and emerg. The priority defines the severity of the message being logged. All iptables messages are logged through the kern facility.

The default TinyNet syslog.conf will put messages with facility kernel and priority error in /var/log/messages.

Adding kern.=error   -/var/log/iptables to your syslog.conf file, and then writing all your iptables rules with a -j LOG target to have --log-level error would make the messages appear in the /var/log/iptables file rather than /var/log/messages (note that there may still be other messages here from other parts of the kernel that use the error priority).

For example, after adding the IPtables rule with a LOG target

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j LOG --log-level error --log-prefix "iptables Null Scan: "

Send three packets to test the rule - the default for hping is the "Null Scan" (no flags set).
Check the Quick Reference :: hping2 page on the menu for the most important command switches.

hping -c 3 192.168.56.101

With the default syslog configuration, this will appear at the end of /var/log/messages
Nov 14 07:04:39 myty-gw kernel: iptables Null Scan: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.56.101 DST=192.168.56.101 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=60450 PROTO=TCP SPT=1897 DPT=0 WINDOW=512 RES=0x00 URGP=0 
Nov 14 07:04:40 myty-gw kernel: iptables Null Scan: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.56.101 DST=192.168.56.101 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=50860 PROTO=TCP SPT=1898 DPT=0 WINDOW=512 RES=0x00 URGP=0 
Nov 14 07:04:41 myty-gw kernel: iptables Null Scan: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.56.101 DST=192.168.56.101 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40201 PROTO=TCP SPT=1899 DPT=0 WINDOW=512 RES=0x00 URGP=0 
  • iptables Null Scan
    The prefix specified in the rule with the --log-prefix option
  • IN=lo
    Interface that was used for an incoming packet (localhost in this case). This will be empty for outgoing packets.
  • OUT=
    Interface that was used for an outgoing packet. This will be empty for incoming packets.
  • MAC= ~~~
    Layer 2 Mac address
  • SRC= ~~~
    The source ip-address from the packet header (hping can spoof this!)
  • DST= ~~~
    The destination ip-address
  • LEN= 40
    Length of the packet
  • TOS=0x00   PREC=0x00   TTL=64   ID= ~~~
    Flags in the IP header of the packet
  • PROTO=TCP   SPT=1899   DPT=0
    Protocol, Source Port, Destination Port. Note how hping starts with a random source port and shifts up one for each packet. Check Quick Reference :: hping2 on the menu for the flags to control the source and destination ports in the header.
  • WINDOW=512   RES=0x00   URGP=0
    Flags in the TCP header of the packet. These will be different for UDP and ICMP.


Service Filtering: TCPwrap

In general terms, a TCP wrapped service is one that has been compiled with the libwrap library These typically include sshd, sendmail, xinetd, etc.. When a connection attempt is made the service checks if connection is allowed based on rules in /etc/hosts.allow and /etc/hosts.deny. If no rules for the service are found in either file, or if neither file exists, access to the service is granted. If a client host is allowed to connect, TCPwrap releases control of the connection to the requested service and does not interfere further with communication between the client host and the server.

To determine whether a given executable supports TCP Wrappers, use ldd /path/to/daemon | grep libwrap

Because access rules in hosts.allow are applied first, they take precedence over rules specified in hosts.deny. Therefore, if access to a service is allowed in hosts.allow, a rule denying access to that same service in hosts.deny is ignored. Since the rules in each file are read from the top down and the first matching rule for a given service is the only one applied, the order of the rules is extremely important. If no rules for the service are found in either file, or if neither file exists, access to the service is granted.

Changes to the hosts.allow and hosts.deny are dynamic: they take effect as soon as the file is saved. A good starting point is to specify only the clients you want to allow to use particular services and then deny everything to everybody else.

So, hosts.deny can simply specify
ALL:ALL
with any specific rules in hosts.allow - enforcing "What is not allowed is denied".

Turning this around by putting ALL:ALL in hosts.allow with specific rules in hosts.deny also works - enforcing "What is not denied is allowed".

Using the except option, the hosts on the left hand side of the : are denied access, but the hosts in the right hand list are allowed.

So for example, if this rule appears in /etc/hosts.allow, all example.com hosts are allowed to connect to all services except cracker.example.com If this rule appears in /etc/hosts.deny, only cracker.example.com has access to all services, and other example.com hosts have access to none
ALL : .example.com EXCEPT cracker.example.com
Given that, what is the effect of this?
ALL EXCEPT telnetd : 192.168.0. 
Using this approach, it is good practice and a good habit to explicitly allow or deny hosts in a single rule by adding the allow or deny directive as the final option.

For example, with ALL:ALL in hosts.deny, we can have this in hosts.allow
imapd: .tinynet.edu :allow
sshd:  .tinynet.edu except public1.tinynet.edu, public2.tinynet.edu :deny
The . before the domain name is a "wild card" and means all hosts ending with tinynet.edu, and since this is in hosts.allow, :allow and and :deny are not really necessary, but make the intent clear.

The tcpdchk command will examine your TCP Wrapper configuration and report all of the potential and real problems it can find.

One important note: if the last line of a hosts access file is not a newline character (created by pressing the Enter key), the last rule in the file fails and an error is logged. This is also the case for a rule that spans multiple lines without using the backslash \ character.

IPtables or TCPwrap? or xinetd?

IPtables filters individual packets at layer 3 and 4. It is fastest, but rules are more difficult to write, and it requires a restart when rules are changed. It is the most widely used because it is scalable and has active support from the Linux kernel developers.

TCPwrap controls initial access to a service. It is simpler, rules take effect immediately, and you can use domain names. However, in practice it is not widely used, with most Linux distros favoring PAM instead (see User Accounts under Host Management on the menu). Slackware still prefers tcpwrap to PAM, so if you want PAM for your TinyNet you need to install it from a Slackware Current archive.

xinetd has many of the same advantages as TCPwrap for protecting the services it runs. One thing that xinetd has that the others do not is the ability to control access using time intervals when the service is available. SENSOR is another interesting unique feature: it replaces the service with a sensor that detects accesses to the specified port. When an access is made, the IP Address is added to a global no_access list until the deny_time setting expires. This flag should be used only on services that you know you don't need, but can be useful to find malicious outsiders.

All in all, this means we may want to use a combination of tools to meet the goals of our security policy. The bottom line is: don't have redundant rules. There are lots of ways to divide things up, and as a systems administrator you need to use the logfiles over time to see traffic patterns and make informed decisions.



RHEL 9 Reference Guide
15. TCP Wrappers and xinetd......................... 205
15.1. TCP Wrappers.................................. 205
15.2. TCP Wrappers Configuration Files.............. 206

16. iptables ....................................... 219
16.1. Packet Filtering ............................. 219
16.2. Differences between iptables and ipchains .... 220
16.3. Options Used in iptables Commands............. 221
16.4. Storing iptables Information ................. 227