Allow, Deny and Remove with Advanced Policy Firewall (APF)

I noticed a few requests for this, so I’m going to make a quick post about it. There are a few ways of manipulating APF (Advanced Policy Firewall by R-fx Networks) to allow and deny who you want.

If you’re looking for information on how to configure APF, this isn’t the post for you. Check out Linux Software Firewalls which covers some of the key configuration settings you’ll need to consider when setting it up. Alternatively, check out APF documentation – it’s rather good. If you’re still stuck, leave a comment.

Direct Command Line

Using the apf command via SSH has to be my preferred method of adjusting the firewall. To deny a source you can simply type:

apf -d <source> [comment]
apf -d 123.45.67.89 Keepings dosing the server

If you have a default deny policy and only want to allow on an individual basis then you can use a command like this:

apf -a <source> [comment]
apf -a 123.45.67.89 Melbourne office allow complete access

Another handy parameter I didn’t learn about until later (much regretted) is the -u one. It will remove the IP source from either allow or denied if it exists. Saves you modifying the rule files directly and restarting the firewall. So to remove a source use:

apf -u <source>
apf -u 123.45.67.89

A catch with remove though, if you have denied 123.45.0.0/16 and you want to remove 123.45.1.56 from the deny rules, it won’t work like this. You can’t apf -u 123.45.1.56 and expect it to work – the tool searches for the parameter you’ve provided and searches any matching rules. These obviously won’t match. If you want to deny 123.45.0.0/16 but suddenly want to allow 123.45.1.56, I’d try apf -d 123.45.0.0/16 and then apf -a 123.45.1.56. I think the results will vary depending on your default policy (not 100% sure on that though).

After using these commands you do not need to restart or reload your firewall. They are invoked straight away as a part of the command. Using apf -r will be pointless in this case.

Looking for example of <source>? I’ve explained it more below.

Direct Rule File Modification

So firstly, your base directory is /etc/apf/ – you’ll find all the configuration files and rules in there.

There are the two main rule files you need to worry about. Don’t worry about the others:

$ ls /etc/apf/{allow,deny}*.rules
/etc/apf/allow_hosts.rules  /etc/apf/deny_hosts.rules

If you open either of these files, there should be rather in-depth instructions contained within:

# Format of this file is line-seperated addresses, IP masking is supported.
# Example:
# 192.168.2.1
# 192.168.5.0/24
#
# advanced usage
#
# The trust rules can be made in advanced format with 4 options
# (proto:flow:port:ip);
# 1) protocol: [packet protocol tcp/udp]
# 2) flow in/out: [packet direction, inbound or outbound]
# 3) s/d=port: [packet source or destination port]
# 4) s/d=ip(/xx) [packet source or destination address, masking supported]
#
# Syntax:
# proto:flow:[s/d]=port:[s/d]=ip(/mask)
# s – source , d – destination , flow – packet flow in/out
#
# Examples:
# inbound to destination port 22 from 192.168.2.1
# tcp:in:d=22:s=192.168.2.1
#
# outbound to destination port 23 to destination host 192.168.2.1
# out:d=23:d=192.168.2.1
#
# inbound to destination port 3306 from 192.168.5.0/24
# d=3306:s=192.168.5.0/24

The developer has done very well explaining the possible syntax and formats you can use. The only thing I can add to it is keep it simple where possible. If you just want to completely drop, firewall, deny or block an IP address from interacting with your server, just add the IP on a new line in the /etc/apf/deny_hosts.rules file (see post changes section below).

If you want to allow your Perth based office to access SSH on your server which is closed by default, you could add something like this on a new line to /etc/apf/allow_hosts.rules (also see post changes section below):

# Perth Office SSH
d=22:s=123.45.1.56

Note that the # is a comment, and everything after it will have no bearing on the rule you’ve added.

Post Changes to Rule/Config Files

After you make a change to your rule or configuration files, you must invoke them by loading them into your firewall. You do this by restarting your firewall:

apf -r

When you restart APF, all rules will be flushed or removed and then re-added effectively implementing the new rule changes you’ve added.

What can I block or allow? What types of Source can I use?

In the above examples I’ve used <source>. Source can equal a single IP address, a IP block in Classless Inter-Domain Routing (CIDR) notation or a fully qualified domain name (FQDN). Examples of each:

Single IP – 123.45.67.89

IP Block (CIDR) – 123.45.0.0/16 (which equates to 123.45.0.0 to 123.45.255.255)

FQDN – nyoffice.domain.com or 13371.dnshost.net

How do I Allow/Block an IP Range?

I’ve also seen a heap of requests specifically about allowing/blocking a range of IP addresses in APF. You can’t do this as “block A to B” – it needs to be in the form of CIDR notation. I use this IP Address Range Calculator to CIDR tool to calculate the CIDR notation for me. I’m lazy and its reasonably accurate.

If you’re looking to block 123.45.67.89 to 123.45.67.91, I’d personally just add them manually. IP’s fit into CIDR specially and you won’t cleanly be able to block 123.45.67.89 to 123.45.67.91 without blocking other IP addresses surrounding them. Don’t be surprised if you’re given multiple CIDR blocks in the results either – it means your supplied IP range crosses multiple blocks.

4 Comments

Emails Not Sending – defer (111): Connection refused (Exim) and SMTP Tweak

I got a phone call today from a client who’s accounts we’d transferred between two cPanel servers on Friday. Today, Monday about 12pm I get a call saying he’s receiving emails but can’t send. I’m told that there aren’t any error messages or bounced replies, but the receivers haven’t got the emails. So I took his details and said I’d call back.

Usually I see this happen if there is a problem with DNS, particularly with the hostname. The server’s hostname should always point to the primary IP address of the server. There should also be a reverse DNS (rDNS) or pointer setup on that IP address pointing back to the hostname. For example:

fileserver.domain.com.au -> 123.45.67.89
123.45.67.89 -> fileserver.domain.com.au

If you don’t do this, you’re asking for trouble. Most providers won’t accept email from you if you don’t setup your DNS properly. For example, here is a message from AOL:

$ telnet mailin-04.mx.aol.com 25
Trying 64.12.90.66…
Connected to mailin-04.mx.aol.com.
Escape character is ‘^]’.

220-Effective immediately:
220-AOL may no longer accept connections from IP addresses
220 which no do not have reverse-DNS (PTR records) assigned.
quit
221 2.0.0 Bye
Connection closed by foreign host.

In the past I’ve seen the server hostname accidently changed causing a mismatch, and in turn this problem.

However the actual cause of my problem today was caused by playing with cPanel settings I was unclear of. What does SMTP Tweak do exactly? It’s very poorly explained… well no, it’s not explained at all in Web Hosting Manager (WHM), but I extracted this from the cPanel docs explaining SMTP Tweak:

SMTP Tweak

You may want to prevent users from bypassing your mail server to send mail. This is common practice for spammers.  This feature allows you to configure your server so that the mail transport agent (MTA), Mailman mailing list software, and root user are the only accounts able to connect to remote SMTP servers.

Source: http://docs.cpanel.net/twiki/bin/view/AllDocumentation/WHMDocs/TweakMail

If your clients are not setup to handle sending mail as an authenticated user, suddenly enabling SMTP Tweak in WHM will cause…

mailin-01.mx.aol.com [205.188.146.193] Connection refused
cluster9.us.messagelabs.com [216.82.242.19] Connection refused
cluster9a.us.messagelabs.com [95.131.108.66] Connection refused
xxx@xxx.com.au <xxx@xxx.com.au> R=lookuphost T=remote_smtp defer (111): Connection refused
mailipao.vtcif.telstra.com.au [202.12.144.27] Connection refused
xxx@telstra.com <xxx@telstra.com> R=lookuphost T=remote_smtp defer (111): Connection refused
gmail-smtp-in.l.google.com [209.85.221.11] Connection refused
alt1.gmail-smtp-in.l.google.com [216.239.59.27] Connection refused
alt2.gmail-smtp-in.l.google.com [74.125.79.114] Connection refused
alt3.gmail-smtp-in.l.google.com [72.14.221.27] Connection refused
alt4.gmail-smtp-in.l.google.com [209.85.216.62] Connection refused

Uhoh. cPanel’s SMTP Tweak does this by adding these rules to iptables:

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  —  anywhere             localhost           tcp dpt:smtp
REJECT     tcp  —  anywhere             anywhere            tcp dpt:smtp reject-with icmp-port-unreachable

So in the end, it had nothing to do with his migration. It was a simple mis-click of SMTP Tweak. At least we know for certain what it does! It effectively firewalls your outbound connection from the server unless you’re an authenticated user, making it appear as if the destination server is blocking you. Unless you look carefully it has the potential to be confusing.

mailin-01.mx.aol.com [205.188.146.193] Connection refused
cluster9.us.messagelabs.com [216.82.242.19] Connection refused
cluster9a.us.messagelabs.com [95.131.108.66] Connection refused
xxx@xxx.com.au <xxx@xxx.com.au> R=lookuphost T=remote_smtp defer (111): Connection refused
mailipao.vtcif.telstra.com.au [202.12.144.27] Connection refused
xxx@telstra.com <xxx@telstra.com> R=lookuphost T=remote_smtp defer (111): Connection refused
gmail-smtp-in.l.google.com [209.85.221.11] Connection refused
alt1.gmail-smtp-in.l.google.com [216.239.59.27] Connection refused
alt2.gmail-smtp-in.l.google.com [74.125.79.114] Connection refused
alt3.gmail-smtp-in.l.google.com [72.14.221.27] Connection refused
alt4.gmail-smtp-in.l.google.com [209.85.216.62] Connection refused
2 Comments

Linux Software Firewalls

There is one main firewall script I use everywhere. It is extremely simple to use and installs quickly.

Advanced Policy Firewall (APF)

Simple Settings to Configuring APF

My preferred text editor is vim, use nano or whatever else you prefer. Substitute my preference with your own with the below commands.

vi /etc/apf/conf.apf

This is the config file. As a sysadmin, I hate wasting time typing things out and therefore love being able to type “vi /etc/apf/conf” and then press Tab to finish the command for me. Well named guys.

DEVEL_MODE

Be familiar with DEVEL_MODE, you need to have it turned off for production operations. With it turned on, your firewall rules will flush to to none every 5 minutes. It’s designed for you to test your settings work, but if you lock yourself out you’ll get access in 5 minutes time again.

IFACE_IN / IFACE_OUT

If you’re using a virtual machine, you may have something other than eth0. Be sure to change it to the untrusted or public network interface.

SET_MONOKERN

If you install APF on a virtual machine, VPS, VE (virtual environment), or whatever you want to call it, and you don’t have access to the kernel you might have to change this to 1 for it to work.

SYSCTL_SYNCOOKIES

This will turn on syn cookies for you. Can help filter out SYN denial of service attacks by flagging packets.

IG_TCP_CPORTS

The permitted inbound TCP ports. Very important. Basically put in all the port numbers you want to be publicly open. For example, HTTP (80) and DNS (53). If you want to allow access to certain IP addresses only, but not the world, don’t include them here.

IG_UDP_CPORTS

The permitted inbound UDP ports. I see FTP (21) and DNS (52) in these a lot, I don’t think it is necessary though.

IG_ICMP_TYPES

Internet Control Message Protocol (ICMP) or commonly called ping (basically the ping command uses this protocol to test connections). Each type of ICMP state corresponds with a number, which you can permit or block. Read about the states and results on Wikipedia, I’m not going into them. The idea being you  can block ping on your server, if a hacker pings you to see if your host is online it can response with request timed out, and they might move on.

EGF

“Outbound (egress) filtering”. Set to 0 or disabled by default. It allows you to filter outbound connections to your server. This is the master on/off switch for the feature.

EG_TCP_CPORTS

Outbound TCP Ports to allow.

EG_UDP_CPORTS

Outbound UDP ports to allow.

EG_ICMP_TYPES

Outbound ICMP or ping types to allow. Again, read about the states and results on Wikipedia to save me going into it.

Other Firewalls – CSF (ConfigServer Security &  Firewall)

If you use a cPanel server, CSF (ConfigServer Security &  Firewall) is very popular and integrates with Web Hosting Manager (WHM). I’m not going to talk about it here, but check out the feature lists and download it at the developers website, ConfigServer.

Leave a comment