banner
 
 
If you appreciate the information found on this website, please drop me a line!

Who's Online

We have 22 guests and 1 member online
Content View Hits : 434539
moon and stars
IPOpener - Block everything and allow to few (The power of dynamic rules).
Thursday, 20 January 2005 19:06
IPOpener, open your ports to people you trust. Close them to everyone else.
Perfect for granting dynamic hosts access to trusted ports!

Update Mar-21-2007: Code and project updated, will update article in future to reflect new changes...and document code better...
Download 1.0 [latest]

Update: Mar-25-2005
I've now integrated the bash scripts from another article on my site which allows you to trust given dynamic DNS host entries. This means that you've got a way to open your iptables based firewall to trusted hosts which are not statically assigned. The remote host will not have to install a client to constantly update the server's IP address. Instead, the remote server will lookup the dDNS based DNS record. (pretty slick..and easy)
The scripts are documented inside my article on iptables..[here]
One day soon maybe I'll merge the content and explain better....don't have time now.

A while ago I read an article in the Linux Journal about Port Knocking. Port knocking allows the system administrator to keep their system invisible while granting access to those with the special "knock". Port knocks are great to increase system security because it defends against system probes. However, port knocking becomes useless on a system that MUST open even a single port. The probing system is aware that the system is listening on that IP and the attacker can focus his attention on that machine.

I'm proposing a new solution that doesn't seek to make your system invisible but instead helps maintain control of the sensitive ports which only trusted users should have access.

Instead of closing all ports. (something that most system can't do because they MUST provide services to the outside world). We setup port authorization on an existing external service. A perfect candidate for this solution is the webserver. Webservers typically allow traffic to ports http(80) and optionally https(433). Almost every system I have ever setup includes a webserver. In addition, most webservers run as non-root users so exploits on webservers are typically safer than root run servers like ssh.

The problem with just opening traffic to HTTP is that we still require other ports to be open for management and content submission. We'd like to be able to login from time to time using ssh but we don't want to open ssh to the world. Leaving ports open that are required for the outside world is dangerous because of potential software bugs. Software bugs in things like sshd lead to system compromise.

The solution is to create a place on your webserver that is password protected and encrypted. These requirements are easy to setup using a webserver like apache. Details on apache installation and setup with https are outside the scope of this document and can be found easily on google.

Once we get a place setup for authorized users to login. Users can begin to login to the site. If the user is an authorized user, their incoming IP is logged to a database and iptables is notified of the change. The webserver then indicates to the user that he may now connect to the authorized ports.

The benefits of a system such as this is that your may keep all unnecessary ports closed to everyone except those with password access. Users don't have to install software to open ports on your machine, all that is required is a web browser. Once users login to the authorized site, trusted port access can be granted indefinitely or for a brief period of time. Since users are required to login to the website before using the trusted ports, you have an audit trail which can be used to "track down" the user who is causing problems with the trusted service.

Installation and management of IPOpener is very easy.
Users and port access is all managed from a database. At this point it is done using mysql but other databases are possible.
Create a database and grant permission to a database user. Create the following table in the database:
 
CREATE TABLE `weballow` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(40) DEFAULT NULL,
  `name` text NOT NULL,
  `source_ip` varchar(20) NOT NULL DEFAULT '',
  `dest_port` varchar(4) NOT NULL DEFAULT '',
  `dest_proto` varchar(4) NOT NULL DEFAULT '',
  PRIMARY KEY  (`id`)
) TYPE=MyISAM AUTO_INCREMENT=9 ;
 

Then insert some user that can access the trusted ports.
For example I might want the guest user to be able to access the port for ssh. I would simply insert the following SQL into the database.
 
INSERT INTO `weballow` (`username`, `name`, `source_ip`, `dest_port`, `dest_proto`) VALUES ('guest', 'A guest user', '', 'ssh', 'tcp');
 

Then you can simply setup an .htaccess that only allows certain users access to a web accessable directory. In this cause I would only allow the user guest access. Inside the protected directory I would create an index.php that would update the user's IP and notify the system that IPTables should be updated with the user's new IP address. A sample index.php is shown below:
 
<?php
$REMOTE_USER=$_SERVER['REMOTE_USER'];
$REMOTE_ADDR=$_SERVER["REMOTE_ADDR"];
include "ipopenerinc.php";
$ipopener= new ipopener();
if($ipopener->init()) {
   if($ipopener->update_addr($REMOTE_USER, $REMOTE_ADDR."/32")) {
      echo "<font color=#ff0000>Changed access IP address. Wait 2 minutes before accessing trusted ports.</font>
";
   }
} else {
  echo "<font color=#ff0000>ERROR! IPOpener failed. Contact administrator.</font>
";
}
echo "Hello there ".$REMOTE_USER ." coming from: ".$REMOTE_ADDR."
";
?>
 
Now when the user guest logs into the protected directory using his webbrowser, the system will update the database with the new IP address that should have access and automatically add the rule to iptables.

Here is the included ipopenerinc.php file
 
<?
   require_once('DB.php');    // Include the Pear::DB class code
   $VERSION = "1.1";
 
   class ipopener_rule {
      var $id;
      var $name;
      var $source_ip;
      var $dest_port;
      var $dest_proto;
   };
 
   class ipopener {
      var $db;
      var $table_user="webusers";
      var $table_allow="weballow";
      var $dsn = array('phptype'  => "mysql",
                       'hostspec' => "localhost",
                       'database' => "ipopener",
                       'username' => "root",
                       'password' => "");
 
      function init($db=NULL) {
         if($db==NULL) {
             $db=DB::connect($this->dsn);
             if (DB::isError($db)) {
                 echo "An error occurred while trying to connect to the database server.
\n";
                 echo "Error message: " . $db->getMessage() . "
\n";
                 echo "A more detailed error description: " . $db->getDebugInfo() . "
\n";
                 return false;
             }
             $db->setOption('debug', 8);
         }
         $this->db=$db;
         return true;
      }
      function update_addr($username, $ipaddress) {
         // our database isn't opened!
         if(!$this->db) {
             return false;
         }
         $fields_values = array('source_ip' => $ipaddress);
         $res = $this->db->autoExecute($this->table_allow, $fields_values, DB_AUTOQUERY_UPDATE,"username=".$this->db->quoteSmart($username));
         if (DB::isError($res)) {
      $res->getDebugInfo();
            die($res->getMessage());
         }
         return $this->db->affectedRows(); 
      }
   };
?>
 


So this gets the data into your system. But now how do we dynamically add rules to our firewall?
There are a couple of ways to do it. One would be to make an IPTABLES module that actually reads results from the database, another would be to write a simple daemon that monitors the database for changes and executes the appropriate iptable commands, and the last and easiest would be to create a simple cron script to run at a regular interval.

For simplicity I chose to implement it using the last method for now:


Add a cron entry like so (decide yourself how often):
/etc/cron.d/ipopener
 
# Run the ipopener script every 1 minutes
* * * * * root /root/ipopener/cmd/ipopener_apply > /dev/null  2>&1
# Force application every 5 minutes.
# Makes sure that iptable chain not lost in mem, but file on disk unchanged.
*/5 * * * * root /root/ipopener/cmd/ipopener_apply force > /dev/null  2>&1
 


Port Knocking
I thought I may as well include these links on knocking dynamic rules in...
How to safely connect from anywhere to your closed Linux firewall | MDLog:/sysadmin
Last Updated ( Tuesday, 11 November 2008 06:36 )
 
 
How did you find my site?
 
How often do you answer random online questions?
 

Random Quote

There is grandeur in this view of life, with its several powers, having been originally breathed into a few forms or into one; and that, whilst this planet has gone cycling on according to the fixed law of gravity, from so simple a beginning endless forms most beautiful and most wonderful have been, and are being, evolved.
--Charles Robert Darwin
Easter4_Adjusted
IMG_2390
100_1846
P1010126
SIGNATURE="personal website"