Main | SourceForge Logo

HOWTO for PCX Firewall 2.x

First, download the software and install it.  The easiest is if you use the rpms.  Read the README file included with the distribution.  If you installed via rpm, it will be in /usr/share/doc/pcx_firewall-2.x.

Secondly, peruse the man pages for the available modules.  You can either read them on-line or in the man directory (wherever the documentation was installed).

Thirdly, edit the module.  It should be located at /usr/lib/pcx_firewall/PCXFireWall/ (rpm installation).

Fourthly, run /usr/lib/pcx_firewall/generator all Rules.  (Specifying Rules or your own Rule Module is only available as of Version 2.2)  Then copy the files in the output directory to /etc/pcx_firewall.  Run /etc/pcx_firewall/startfw to start your firewall and test it.

As of Version 2.2 you can specify the Rules file to work with on the command line.  If you do not specify anything, it defaults to Rules.  The file specified must exist in the PCXFireWall directory and must end in a .pm extension.  (Ex. would be usable as test.)  There is a file in the doc directory (rpm install) or in the base directory of the tarball.  Copy it into PCXFireWall naming it without any spaces in the name (perl modules can not have spaces in them) and then edit the file and replace the word Template with The name of the file minus the .pm extension.  Then put your rules in the same locations as you would if editing since this is a stripped down version of  In the future, when new Table Modules are added, to get access to those modules, you would just use the latest version of to put your rules in.  It will have defined the variables that will allow you to work with the new table modules.  If you don't upgrade your rules files, then you would only have access to the Filter, Mangle and NAT modules.

As of Version 2.4 when you specify a Rules file to work with the generated files are now placed in a directory named after the Rules file you are using.  For Example if you used the rules file (generator all test) then the generated files would be placed in directory test.  To have the install script work with the files just generated you will now have to specify the -s sourcedir option.  In this example you would install the files as follows: install -s test.   This would pull the startfw, stopfw and restartfw scripts from the test directory and place them in /etc/pcx_firewall/.  If you wanted the destination directory to be under /usr for instance you could use the -r root dir option to specify the root directory to prefix /etc/pcx_firewall with.   To complete this example you would have install -r /usr -s test to pull the files from the test directory and put them in /usr/etc/pcx_firewall.  Note: If you do not specify either -r or -s options for the install script, it will use the defaults of "" for -r and "output" for -s.

As of Version 2.8 all /proc related manipulation is now done in the Proc module and is available via $proc in the file. You should use the latest module and integrate your rules into it. See the file for examples of setting ipForwarding, synCookies, etc.

The only file you should have to modify is  In it you will find 3 methods defined (startingRules, stoppingRules and restartingRules). These methods have passed into them the available modules we have defined.  These modules are (Config, Interfaces, Filter, NAT and Mangle).

Programming Note: Passing parameters to the defined methods is as follows: parameter name => parameter value, parameter name => parameter value, ...
If a parameter name has a - in it, wrap the parameter name in double quotes (ex. "to-source" => "").
If the parameter value is a string, then wrap it in double quotes.  See last example.
Parameter Names are CASE sensitive.  If you change the case then it will not be seen and the default will be used that the method provides.
Anything after a # is considered a comment to perl, as long as it is outside a string.

In each of the above methods, you can use the available modules to define what you want to happen in your firewall.

The perl program generator is responsible for instantiating each of the above mentioned modules and for calling the methods provided by Rules so as to generate the startfw, stopfw and restartfw shell scripts which will actually do your dirty work.

You do not have to define any network interfaces, but this will prevent you from using the inInterfaceIP and outInterfaceIP strings when specifying source (s) and destination (d) addresses to the functions.  You can classify your interfaces as internal, external or dmz.  There are methods provided by the Interface module to get all interfaces defined for a specified location (internal, external or dmz) and to get the info you defined for a specific interface.  You can create IP Aliased interface entries (ex. eth0:0), but when it is used in the generated rule, it will be referenced as the interface without the :X part (ex. eth0). This is because iptables does not support aliased interfaces and in reality, all that is different between the interfaces is the IP Address it responds to.

Since the "Rules" are being programmed in perl, you have the ability to use perl loops, conditional statements, etc. to help implement your firewall ruleset.   One possible use could be when you want to generate the same rule, but have different interface and IP values assigned.  You could get the list of interfaces you defined that match your requirements (ex. all internal interfaces) and then loop over them while defining your ACCEPT, DROP, JUMP, etc. command.

Ex: (Define 3 interfaces.  Drop and Log all traffic coming to the internal interfaces that isn't ssh.)
  $interfaces->defineInterface(name => "eth0", location => "external", type => "dynamic"); # location => "external" is assumed, so it could be left out.
  $interfaces->defineInterface(name => "eth1", location => "internal", type => "static", IP => ""); # type => "static" is assumed, so it could be left out.
  $interfaces->defineInterface(name => "eth2", location => "internal", IP => "");

  my %internalInterfaces = $interfaces->getInterfacesLocatedAt(location => "internal"); # get the hash of internal interfaces.
  foreach my $interface (keys %internalInterfaces)
    $filter->drop(chain => "INPUT", i => $interface, d => "inInterfaceIP", dport => "! 22", log => 1, "log-prefix" => "Blocked Port");
    $filter->accept(chain => "INPUT", i => $interface, d => "inInterfaceIP", dport => "22"); # Accept ssh traffic to the internal interfaces of the firewall.

If you want some comment or shell script to be output/executed before and/or after the rule being generated, provide your text in the preComment and postComment parameters to the method.  So in the previous example, if you wanted the following comment "# Accept ssh traffic to $interface." placed before the accept rule you would add the following parameter to the accept method call. preComment => "\n# Accept ssh traffic to $interface.\n". This would cause $interface to be expanded on each loop through the foreach statement so that you would get eth1 and then eth2 output (or however it comes out of the hash).

Do not forget to place a \n at the end of your preComment or postComment strings otherwise they will run into the generated rule which is not what you want.

Notes: As of Version 2.8 it is possible to specify what network related command should be used to determine the dynamic IP address of a dynamic interface. You can specify ifconfig or ip by setting $configObj->{networkCommand} = "command" in your module. Make sure you have the required tool installed if you use ip.