Generating Firewall Rules with Perl
Listing 5. ports.conf
wan tcp 22 # ssh wan tcp 25 # smtp wan tcp 80 # http wan udp 53 # dns wan udp 1194 # openvpn wan udp 5060 # sip wan udp 4569 # iax2 wan udp 10000:20000 # rtp lo all lan tcp 22 # ssh lan tcp 25 # smtp lan udp 53 # dns lan tcp 53 # dns lan udp 67 # dhcp lan udp 68 # dhcp lan tcp 80 # http lan tcp 111 # portmapper lan udp 111 # portmapper lan tcp 143 # imap lan tcp 443 # https lan tcp 2049 # nfs lan udp 2049 # nfs lan tcp 3306 # mysql lan udp 4569 # iax2 lan udp 5060 # sip lan tcp 5432 # postgresql lan tcp 10000 # webmin lan all gig all tun all wifi udp 1194 # openvpn voip udp 5060 # sip voip udp 4569 # iax2 voip udp 53 # dns voip tcp 22 # ssh voip udp 10000:20000 # rtp voip tcp 80 # http
You'll notice that I have a rule that allows all traffic on the lo, or loopback, interface. This is important, because without this rule, many programs break in ways that are hard to diagnose. You also may be asking why I go to the effort of creating so many firewall rules for my LAN interface, only to have an all at the end. I do this for several reasons. The primary reason is that until my kids grow up and get on the Internet, I trust the traffic on my local network. However, by having rules for each service I run, I'm able to extract statistics about how much traffic each service generates. Also, security is an iterative process. Over time, I'll add rules that will further tighten my firewall; eventually, I'll remove the final all from the policy.
Now, back to the add_rules() function. Even though this is the longest function in the entire program, it's still not too hard to understand. The sections of code that deal with tcp and udp rules simply create two rules for each rule in the ports.conf file. One rule is tied to the destination port number; the other rule is tied to the source port number. At first, this may seem odd, because we are policing only inbound traffic. What we're doing is making sure that both inbound and outbound connections are allowed to pass. For example, a packet coming in on the WAN interface with the destination port set to 80 corresponds to an inbound connection to my Web server. On the other hand, an incoming packet on my WAN interface with the source port set to 80 is coming from an outside Web server in response to a request that came from inside my network.
The code that handles the all rules is a special case. In this case, we create a rule on the given interface for each of the protocols. In hindsight, this might be overly complex, but it has an interesting side effect. If the router encounters a packet containing an unknown protocol, such as IPSec, the firewall will fall back to its default policy even though we've asked it to pass all traffic on this interface. So, in a sense, “all protocols” actually means “all known protocols”. I think this is a good thing.
For what it's worth, the script will put firewall rules into the kernel in roughly the same order that they appear in the ports.conf file. I say roughly, because the rules will be put into the appropriate chain depending on which interface and protocol they match against. But within each chain, the rules will be executed in order.
The set_default_action() function creates rules that determine what happens to packets that don't match any previous rules. This sounds very similar to the purpose of the set_default_policy() function, but there is a subtle difference. The set_default_policy() function configures the default firewall policy, and the set_default_action() function creates firewall rules that catch unmatched traffic before the kernel falls back to the default policy, essentially capping each chain. Once these rules match a packet, they create a log entry for the packet, and then they implement whatever policy we want, in this case, DROP. Once again, the log entries allow me to determine what traffic is being dropped and why.
I'm not trying to tell you that this program is perfect, nor will it do everything you want it to do. You might even find bugs in it. In fact, by the time you read this article, I'll probably have made several improvements to the script. As it is right now, the script isn't able to configure any firewall policy for the ICMP protocol. It would be nice to be able to allow outbound ping requests and deny incoming requests, for example. It would also be useful to be able to configure firewall policy for outgoing and routed traffic. And because I'm using VoIP, I'm thinking of changing my script to allow me to configure Quality of Service (QoS). If you come up with useful modifications to this script, I'd like to hear about them.
But there you have it, such as it is. In less than 200 lines of Perl code, I'm able to implement a quite flexible and efficient firewall policy containing potentially hundreds of individual rules. At the same time, making changes to my firewall policy is simple enough that even most beginning Linux users can make correct changes.
Mike Diehl works for SAIC at Sandia National Laboratories in Albuquerque, New Mexico, where he writes network management software. Mike lives with his wife and two small boys and can be reached via e-mail at firstname.lastname@example.org.
Mike Diehl is a freelance Computer Nerd specializing in Linux administration, programing, and VoIP. Mike lives in Albuquerque, NM. with his wife and 3 sons. He can be reached at email@example.com
Fast/Flexible Linux OS Recovery
On Demand Now
In this live one-hour webinar, learn how to enhance your existing backup strategies for complete disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible full-system recovery solution for UNIX and Linux systems.
Join Linux Journal's Shawn Powers and David Huffman, President/CEO, Storix, Inc.
Free to Linux Journal readers.Register Now!
- Back to Backups
- Download "Linux Management with Red Hat Satellite: Measuring Business Impact and ROI"
- Google's Abacus Project: It's All about Trust
- Secure Desktops with Qubes: Introduction
- A New Version of Rust Hits the Streets
- Seeing Red and Getting Sleep
- Fancy Tricks for Changing Numeric Base
- Secure Desktops with Qubes: Installation
- Working with Command Arguments
- Linux Mint 18
Until recently, IBM’s Power Platform was looked upon as being the system that hosted IBM’s flavor of UNIX and proprietary operating system called IBM i. These servers often are found in medium-size businesses running ERP, CRM and financials for on-premise customers. By enabling the Power platform to run the Linux OS, IBM now has positioned Power to be the platform of choice for those already running Linux that are facing scalability issues, especially customers looking at analytics, big data or cloud computing.
￼Running Linux on IBM’s Power hardware offers some obvious benefits, including improved processing speed and memory bandwidth, inherent security, and simpler deployment and management. But if you look beyond the impressive architecture, you’ll also find an open ecosystem that has given rise to a strong, innovative community, as well as an inventory of system and network management applications that really help leverage the benefits offered by running Linux on Power.Get the Guide