Disclaimer and warning: I suggest you read this entire blog post first before running anything and do some testing locally if you can, or at least read the contents of each script, before running them. I accept absolutely no responsibility for you locking yourself out of your server using these scripts. They worked for me on FreeBSD 6.2 and FreeBSD 6.3. At the very least you should do these on a remote machine that is not currently in production.

I had a whole bunch of firewall rules running on my gateway for various servers. It became cumbersome administrating them all centrally, so I decided that it would be much better to have all my servers run their own firewall rules.

My servers are in a different city, so I had to do this all remotely. Unfortunately playing around with ipfw remotely is pretty dicey because you generally have the ability to completely lock yourself out of your server.

The Code

So, without further ado, here is my set of scripts for safely doing ipfw stuff remotely:


That tarball contains the following files:

  • add_rules_safely: the script you call to add rules safely
  • add_rules_then_flush: used by add_rules_safely
  • ipfw_flush: called by add_rules_then_flush if it's not killed
  • kldload_ipfw_safely: the script you call to initialise ipfw on a server
  • kldload_ipfw_then_allow: called by kldload_ipfw_safely
  • rules_to_add: a list of firewalls you want to add


When you're running this on a server which doesn't have ipfw compiled in the kernel, you can either compile it into the kernel, or you can load it into the kernel dynamically by doing (as root):


Once you're happy with your rules, you can load ipfw automatically in /boot/loader.conf (or statically compile it into the kernel), but until then it's best to leave it out so that if you really mess up you can always just power cycle the machine and ipfw won't be there anymore.

Once you've got ipfw running, you should be able to do (as root):

ipfw list

which will display:

00010 allow ip from any to any
65535 deny ip from any to any

Now, having done that, you can test out the script to add rules safely. By default when you first download the tarball above, and kldload ipfw safely using the command above, you'll have a rule 00010 which allows any to any. The rules_to_add file as you downloaded it will delete this rule, locking you out of your server. The "sleep" value in add_rules_then_flush as you downloaded it is 10, so if you were to do:


with the files downloaded in that tarball "out of the box" so to speak, you would be locked out of your server for 10 seconds, then the rules will be flushed and you will be able to get back in.

Now, the general procedure for adding more rules will be to first of all edit the sleep interval in add_rules_then_flush to something that will allow you to kill that script if your rules did not block you out, then put some more meaningful rules in your rules_to_add file.

What this means is that you'll be able to add your rules safely. If all goes well, and you still have access to your box, then you'll be able to kill the script before it flushes your rules.

If you experience ipFAILw, and you get locked out of your server, then after the sleep interval is over, your rules will get flushed and you can log back in.

Comments Archive

This post originally appeared on an older version of the Working Software website which implemented it's own comment mechanism. This new version of our website/blog uses Disqus for comments (see below) however I wanted to preserve the comments made on the previous post here:


jsoftw (2008-08-27)

UPDATE Wednesday December 29, 2010 14:06 GMT+11: This article has been updated again with details of the project hosting at github: International Mobile Number Validation PT III

I've setup anonymous CVS access so that everyone can maintain this file. In order to access the file, just do the following:


You will be able to commit that file. The password is empty:


Your commits will be automatically added to the live file at:

The serial number is automatically incremented and prepended to the top of the file via a cron job that runs once per minute. When you commit, include a commit message with what you changed or added, and your name. The commit messages will be published here using the CVS log:

To stop invalid file formats from sneaking in, the automated update system will test parsing the file before publishing it, and will email me if there is a problem. Please try not to break it though, and only update numbering information that you're sure of.

As mentioned in my last post, there is also a sample implementation of how to parse this file in a PHP5 class which you can also access via anonymous CVS:


However access to that project is read only.

Please feel free to contact me if you have any questions, or you can simply subscribe to the users@kannel.org mailing list.

Happy validating!


I wanted to do an anonymous read only CVS repository over SSH for my RocketSled framework. I already had a FreeBSD jail setup for my CVS repository, but I didn't want to just hand out an SSH login on it, and I also didn't want to have two repositories (one readonly and one read/write).

So the goal is to have an easy/safe way for one public CVS user to be able to execute only CVS commands and have read only access to one or more projects in my repository, whilst still allowing me to hand out logins to trusted developers for read/write access to that and other projects in the same repository.

Creating a Public CVS User

For starters, I created a script called cvs-shell:


and put the following content in it:


The umask above means that, later when our development team and the public user share a lock directory with the "set gid" bit set on it, they will not prevent each other from checking out files. I then added a passwordless user bentley in the group bentley and made that script bentley's shell. Now when that user logs in, the only command they have access to is the cvs server command. You can try logging in now

ssh bentley@rs.workingsoftware.com.au

It's worth noting here that there are other ways of restricting SSH to only a single command, however this involves having to download and install a private key and I figured that the above was easier. That being said I'd love to know if there's some massive security flaw with doing things that way. From what I can find around the place there doesn't seem to be any problem with it. Please add a comment if you have any advice!!

Creating the Read Only Repository

I had an existing repository, so I copied it onto my new CVS server:


then as root on rs.workingsoftware.com.au:


Before we can create a read only repository we have to create a spot for CVS to write lock files outside of the repository itself:


Now uncomment the the LockDir line and change it to /var/lock/anoncvs and save the file, then check the changes in with:


After I did that I was able to go onto a different server and do:


I tested things out by making a change to the source code and then attempting to commit that change, and I was unable to. Success!

Mixing and Matching

There were two things wrong: firstly, I didn't want to give public access to every project in my repository and secondly, I wanted to allow write access to some of my developers.

This was pretty easy, just a matter of juggling the permissions a bit. First, I created a group cvsdev and added all my developer accounts to it (not the bentley account though). I then granted permission to that group on the LockDir:


I then set permissions on the cvsroot which would allow read only access to the bentley account, and read/write access to users in the cvsdev group, and did the same on the CVSROOT folder inside the repository:


Note that above, for directories have "4" in front of them, which means that the "set gid" bit is set on those directories. This means that files that are created in those directories will inherit the group cvsdev. You should then change the umask for each of your developer accounts to 002, so that new files created in your repository are writable by all members of your development team.

Now for any project that you want to provide anonymous access to, you do the following (using RocketSled as an example):


Users in the cvsdev group will be able to write to the public repository, but the bentley user account will only be able to read from it. Then for any project that you wish to exclude from public read access, but then allow read/write access to your development team:


Because this is all permissions based, even if someone were to h4x0r my bentley@rs.workingsoftware.com.au account, they still wouldn't be able to read my private project files, and since I've got this running on a FreeBSD jail without sendmail or anything installed I doubt there's much fun they could really have. You never know though, I may be eating my words within days.

So that's it! You can now access my public RocketSled repository:


and my development team can checkout using their accounts and commit changes to both the public and private projects.

Incidentally, I'd wait til release v0-5 of RocketSled (which should be within the next month or so) before starting to play around with it. If you want to find out more about RocketSled you can go to:

http://rocketsled.workingsoftware.com.au/ (ed: this link is now broken, refer to the RocketSled page)

We're working on it :)

Comment Archive

This post originally appeared on an older version of the Working Software website which implemented it's own comment mechanism. This new version of our website/blog uses Disqus for comments (see below) however I wanted to preserve the comments made on the previous post here:

In the scenario where I give read/write access to the devs and make the project public. After a developer commits a file he becomes the owner of the file and the readonly user can no longer see it. How did you manage do overcome this?

Anton Avramov (2009-10-10)


Subscribe via RSS

Building software in the real world - the Working Software blog

We write about our experiences, ideas and interests in business, software and the business of software. We also sometimes write about our own products (in order to promote them).