Linux Firewall on a Floppy HOWTO (draft)


Table of Contents

  1. Standard Disclaimer
  2. Introduction
  3. What you need
  4. Description
  5. Quick Start
  6. References
  7. Details
  8. Notes to Myself
  9. Acknowledgements
  10. Contacts

Standard Disclaimer

Use this information at your own risk. If anything breaks as a result of reading this document I, James Wayne Weller, will not be held responsible. I accept no liability for equipment or data lost or otherwise damaged as a result of these procedures. This implementation worked in my case and might work or help in yours. But if there is any damage done you get to keep both pieces

What you need to get started

Easy setup

Articulate setup

You should have linux installed on a working system if you want to do this. It needs minix fs support and ramdisk support.

Introduction

Hi all,
this is my firewall-on-one-floppy howto. The need for this document arose when I wanted to connect my home LAN to the internet over my cable modem. My ultimate (and current) goal was to use linux as an embedded system for a 486 with two ethernet cards and a boot rom to start from the local network. Alas, I don't have boot roms (yet). So, floppy disk is the next best.

Description

The firewall kit is composed of two disks. I know ... I said it fit on one floppy, and it does. The first disk is broken into two parts. The first part is the kernel itself, while the second part is the ramdisk to mount as the root (/) filesystem. The *only* binaries on the ramdisk image are ones *needed* to bootstrap the system, get a console going, and mount further disks. That means that you can boot your system with the first disk, pull the disk, and walk away. It will be firewalling. This boot procedure requires most of the following binaries and scripts.

    /bin/sh         symbolic link to kiss
    /bin/kiss       a very simple shell to type commands at
    /bin/ash        a smarter shell for scripting
    /bin/ifconfig   ties ethernet cards to IPs...
    /bin/route      set network routes
    /bin/login      enables log on at the terminal
    
    
    /sbin/init      daddy process
    /sbin/agetty    prompt for credentials at the terminal
    /sbin/ipchains  ip packet filter configuration tool
    /sbin/dhcpcd    dhcp client daemon (to pull down IP from server)
    /sbin/insmod    needed to insert ethernet module
    /sbin/rmmod     needed to remove ethernet module
    /sbin/fw.sh     an ash shell script to setup firewalling rules
    /sbin/mount     needed to mount floppies
    /sbin/umount    needed to unmount floppies
    

You're probably wondering how your going to get anything done on this box. I mean this is a pretty sparse collection of binaries isn't it? The answer is the second floppy disk. If you want this computer to do more than just sit in the closet and filter packets, you'll need to login as root, insert the second floppy disk, and type...

    [/root]# mount -t minix /dev/fd0 /usr/bin
    

Now, /usr/bin is already in your path. So, now you have access to all the binaries on that minix filesystem. My default /usr/bin/ disk has...

    /usr/bin/ping        send icmp packets
    /usr/bin/netstat     find out what your host is listening for (netstat -an)
    /usr/bin/traceroute  found out the network route your packets take to a host
    /usr/bin/telnet      login to a remote host
    /usr/bin/ftp         file transfer from remote host
    /usr/bin/pico        the end all simple editor
    /usr/bin/grep        look for regular expressions
    /usr/bin/ssh         ssh 1.3 client
    /usr/bin/gunzip      gzip uncompress
    /usr/bin/gzip        gzip compression
    /usr/bin/tar         tape archiver 
    /usr/bin/cat         output files
    /usr/bin/sed         stream editor
    /usr/bin/tail        look at the end of a file
    /usr/bin/yes         output a string until terminated (good for I/O testing)
    /usr/bin/df          shows available diskspace 
    /usr/bin/free        shows memory usage
    /usr/bin/head        output the top of a file
    /usr/bin/passwd      change your password (temporarily b/c ramdisk)
    

Notice, because it's physically seperated from your runtime firewall, bad-guy cracker types don't have access to those (unless you mount the disk after you've been rooted). If you want ultra-security bring down your outside internet interface if your are going to mount the tools disk.

      styx:[/]# umount /usr/bin
    

Quick Start

DOS

Put a disk in the floppy and type

      c:\lfw> rawrite.exe lfw.img a:
    

Put another floppy in the drive

    c:\lfw> rawrite.exe fwtools.img a:
    

Linux

Put a disk in the floppy and type

    cat lfw.img > /dev/fd0
    

Put another floppy in the drive

    cat fwtools.img > /dev/fd0
    

Do the deed

Get a 386 or better motherboard with >= 6mb RAM and hook up two 3com 3c509 ethernet cards ($10~$15) and a 3.5in 1.44mb floppy drive. Yes, that's it :) Make a DOS boot disk and run the 3x509cfg.exe file available from http://www.3com.com. My cards are set to the following values.

       eth0 irq=10 ioport=0x300
       eth1 irq=5  ioport=0x220
      

Plug your internet connection into eth1 and your local network hub into eth0. Make sure you set all you other machines on your network to use any address from 192.168.0.[2-255]. The other machines should have a gateway address of 192.168.0.1 (styx). The gateway is eth0 on the firewall machine (styx).

Slap in the boot disk and turn on that frankenstein monster. You should see a simple kernel description as it straps the hardware. Then you will get a login prompt. The box is now firewalling. You should be able to reach the internet from your computers behind the firewall. You can login as root; the password is Firecracker2000.

NOTE: This only works if there is a DHCP server on your internet connection.

References

Implementation Details

  1. Make a kernel with the features you need. Make sure to compile in your ethernet card as a module. The kernel can be gzipped (make zImage) or bzipped (make bzImage). Since their is no lilo to pass ether= paramaters to we need the probing the modules do. If someone out there knows how to get a static driver to find two cards *let me know*.
  2. Prepare the kernel for booting from a floppy using a ramdisk.

    Find out the size of your kernel

        [/root]# du -h kernel.img
        336K    kernel.img
        

    Write that down, because this is the hard part. The kernel has 16 bits at the beginning of it that set important boot values.

        bits  0-10:  set the offset to the ramdisk in 1024k blocks. unsigned int.
        bits 11-13:  unused bits
        bit     14:  flag indicating whether to load ramdisk. (1) for us
        bit     15:  flag indicating whether to prompt for root fs. (0) for us
        

    Now we need to set up that 16 bits. My kernel image was 336k convert that to a binary value and you get

        366d == 101010000b
                |       |
                8       0
        

    Notice thats only 9 bits and we get 0-10, 11 bits, to use. So pad it with zeros.

        00101010000b
        |         |
        10        0
        

    Now we know that the next three bits are unused so we set them to 0

        00000101010000b
        |            |
        13           0
        

    The next bit is the ramdisk flag. We want to load a ramdisk so we set it to 1.

        100000101010000b
        |             |
        14            0
        

    Finally, the prompt bit. We know exactly where our ramdisk is and it's not on a second media so their is no need to prompt the operator for it. So, we set this flag to 0.

        0100000101010000b
        |              |
        15             0
        

    Now, that we have accounted for that sixteen bit number we can convert it back to decimal and setup our kernel image to use the floppy.

        0100000101010000b == 16720d
        

    Now issue these commands using the numbers you got from the above arithmetic.

        [/root]# rdev  kernel.img /dev/fd0
        [/root]# rdev -r kernel.img 16720
        [/root]# rdev -R kernel.img 0
        

  3. There now, you have a kernel ready to boot from a floppy. The next step is to get a filesystem for that kernel to mount. If your new to devices and permissions then I recommend hacking up my or loaf's root filesystems.

    Note: You'll need ramdisk and minix support in your current kernel.

    Fill the ramdisk with zeros.

        [/root]# dd bs=1k if=/dev/zero of=/dev/ram0
        dd: /dev/ram0: No space left on device
        4097+0 records in
        4096+0 records out
        

    Note: I always think of dd standing for disk duplicate. It is the worlds most articulate copy command.

        bs=     means the size of our blocks.
        count=  means the number of blocks to copy
        if=     is the input file
        of=     is the output file
        skip=   skip this many blocks in the input file
        seek=   skip ahead this many blocks in the output file
        

    Make a 2048k minix filesytem on the ramdisk.

        [/root]# mkfs.minix /dev/ram0 2048
        682 inodes
        2048 blocks
        Firstdatazone=26 (26)
        Zonesize=1024
        Maxsize=268966912
        

    Mount it in a convenient directory

        [/root]# mkdir rd
        [/root]# mount -t minix /dev/ram0 rd
        

    Then put my, loaf's or any other file system in the ramdisk

        [/root]# cd rd
        [/root]# tar -xzf ../filesystem.tar.gz
        

    Now hack, hack, hack in the rd directory until you get a filesystem you want to boot with. Be careful. A booting system is a fragile thing. Move in small undoable steps. Once you have a good filesystem save it.

        [/root]# cd rd
        [/root]# tar -cf ../ramdisk.tar *
        [/root]# cd ..
        

    Unmount the ramdisk

        [/root]# umount rd
        

    fill the ramdisk with zeros to optimize compression

        [/root]# dd if=/dev/zero bs=1k of=/dev/ram0
        dd: /dev/ram0: No space left on device
        4097+0 records in
        4096+0 records out
        

    Make yet another minix filesystem

        [/root]# mkfs.minix /dev/ram0 2048
        682 inodes
        2048 blocks
        Firstdatazone=26 (26)
        Zonesize=1024
        Maxsize=268966912
        

    I like to force a check of it to avoid warnings when mounting

        [/root]# fsck.minix -fa /dev/ram0
        fsck.minix, 1.2 - 11/11/96 / util-linux 2.6
        Forcing filesystem check on /dev/ram0.
        

    Mount the ramdisk again

        [/root]# mount -t minix /dev/ram0 rd
        

    Now put your usable filesystem back in. The reason we do this twice is to make the compression work better. Your tinkering in the rd directory caused fragmentation.

        [/root]# cd rd
        [/root]# tar -xspf ../ramdisk.tar *
        [/root]# cd ..
        

    Good! now we need a copy of the filesystem on the disk called ramdisk

        [/root]# dd bs=1k count=2048 if=/dev/ram0 of=ramdisk
        2048+0 records in
        2048+0 records out
        

    next compress the ramdisk using gzip

        [/root]# gzip -9 ramdisk
        
  4. Great! Now all we need to do is put the kernel and the filesystem you designed onto a floppy disk.
        [/root]# dd bs=1k if=kernel.img of=/dev/fd0
        336+0 records in
        336+0 records out
        [/root]# dd bs=1k seek=336 if=ramdisk.gz of=/dev/fd0
        614+1 records in
        614+1 records out
        

    Note the seek value in the second command is 336. Then, remember that my kernel was 336k. So we put the ramdisk *right* after the kernel.

  5. Now, go boot and see you did :)

Notes to Myself

Aknowledgements

  • Thanks Jason Guild and Tom Kircher for bridging my knowledge gaps.

  • Thanks to all the people who work at and with LDP

  • Thanks to the thousands of developers who made this and all the tools it relies on exist in the first place

  • Thank You GNU

    Contacts

    I am open to ALL suggestions.
    Jim Weller (NOSPAM_jim@jimweller.net)
    Homepage http://www.jimweller.net