FreeS/WAN examples
Keywords: Linux, IPsec, VPN, security, FreeSWAN, examples

# FreeS/WAN script examples

This file is intended to hold a collection of user-written example scripts or configuration files for use with FreeS/WAN.

So far it has only one entry.

## Poltorak's Firewall script

    From: Poltorak Serguei <poltorak@dataforce.net>
    Subject: [Users] Using FreeS/WAN
    Date: Tue, 16 Oct 2001

    Hello.

    I'm using FreeS/WAN IPsec for half a year. I learned a lot of things about
    it and I think it would be interesting for someone to see the result of my
    experiments and usage of FreeS/WAN. If you find a mistake in this
    file, please e-mail me. And excuse me for my english... I'm learning.. :)

    I'll talk about vary simple configuration:

    addresses prefix = 192.168

        lan1          sgw1     .0.0/24 (Internet)       sgw2            lan2
      .1.0/24---[ .1.1 ; .0.1 ]===================[ .0.10 ; . 2.10 ]---.2.0/24

    We need to let lan1 see lan2 across Internet like it is behind sgw1. The
    same for lan2. And we need to do IPX bridge for Novel Clients and NDS
    synchronization.

    my config:
    ------------------- ipsec.conf -------------------
    conn lan1-lan2
            type=tunnel
            compress=yes
            #-------------------
            left=192.168.0.1
            leftsubnet=192.168.1.0/24
            #-------------------
            right=192.168.0.10
            rightsubnet=192.168.2.0/24
            #-------------------
            auth=esp
            authby=secret
    --------------- end of ipsec.conf ----------------

    ping .2.x from .1.y   (y != 1)
    It works?? Fine. Let's continue...

    Why y != 1 ?? Because kernel of sgw1 have 2 IP addresses and it will choose
    the first IP (which is used to go to Internet) .0.1 and the packet won't go
    through IPsec tunnel :(  But if do ping on .1.1 kernel will respond from
    that address (.1.1) and the packet will be tunneled. The same problem occurred then
    .2.x sends a packet to .1.2 which is down at the moment. What happens? .1.1
    sends ARP requesting .1.2... after 3 tries it send to .2.x an destunreach,
    but from his "natural" IP or .0.1 . So the error message won't be delivered!
    It's a big problem...

    Resolution... One can manipulate with ipsec0 or ipsec0:0 to solve the
    problem (if ipsec0 has .1.1 kernel will send packets correctly), but there
    are powerful and elegant iproute2 :) We simply need to change source address
    of packet that goes to other secure lan. This is done with

    ip route replace 192.168.2.0/24 via 192.168.0.10 dev ipsec0 src 192.168.1.1

    Cool!! Now it works!!

    The second step. We want install firewall on sgw1 and sgw2. Encryption of
    traffic without security isn't a good idea. I don't use {left|right}firewall,
    because I'm running firewall from init scripts.

    We want IPsec data between lan1-lan2, some ICMP errors (destination
    unreachable, TTL exceeded, parameter problem and source quench), replying on
    pings from both lans and Internet, ipxtunnel data for IPX and of course SSH
    between sgw1 and sgw2 and from/to one specified host.

    I'm using ipchains. With iptables there are some changes.

    ---------------- rc.firewall ---------------------
    #!/bin/sh
    #
    # Firewall for IPsec lan1-lan2
    #

    IPC=/sbin/ipchains
    ANY=0.0.0.0/0

    # left
    SGW1_EXT=192.168.0.1
    SGW1_INT=192.168.1.1
    LAN1=192.168.1.0/24

    # right
    SGW2_EXT=192.168.0.10
    SGW2_INT=192.168.2.10
    LAN2=192.168.2.0/24

    # SSH from and to this host
    SSH_PEER_HOST=_SOME_HOST_

    # this is for left. exchange these values for right.
    MY_EXT=$SGW1_EXT
    MY_INT=$SGW1_INT
    PEER_EXT=$SGW2_EXT
    PEER_INT=$SGW2_INT
    INT_IF=eth1
    EXT_IF=eth0
    IPSEC_IF=ipsec0
    MY_LAN=$LAN1
    PEER_LAN=$LAN2

    $IPC -F
    $IPC -P input DENY
    $IPC -P forward DENY
    $IPC -P output DENY

    # Loopback traffic
    $IPC -A input -i lo -j ACCEPT
    $IPC -A output -i lo -j ACCEPT

    # for IPsec SGW1-SGW2
    ## IKE
    $IPC -A input -p udp -s $PEER_EXT 500 -d $MY_EXT 500 -i $EXT_IF -j ACCEPT
    $IPC -A output -p udp -s $MY_EXT 500 -d $PEER_EXT 500 -i $EXT_IF -j ACCEPT
    ## ESP
    $IPC -A input -p 50 -s $PEER_EXT -d $MY_EXT -i $EXT_IF -j ACCEPT
    ### we don't need this line ### $IPC -A output -p 50 -s $MY_EXT -d $PEER_EXT -i $EXT_IF -j ACCEPT
    ## forward LAN1-LAN2
    $IPC -A forward -s $MY_LAN -d $PEER_LAN -i $IPSEC_IF -j ACCEPT
    $IPC -A forward -s $PEER_LAN -d $MY_LAN -i $INT_IF -j ACCEPT
    $IPC -A output -s $PEER_LAN -d $MY_LAN -i $INT_IF -j ACCEPT
    $IPC -A input -s $PEER_LAN -d $MY_LAN -i $IPSEC_IF -j ACCEPT
    $IPC -A input -s $MY_LAN -d $PEER_LAN -i $INT_IF -j ACCEPT
    $IPC -A output -s $MY_LAN -d $PEER_LAN -i $IPSEC_IF -j ACCEPT

    # ICMP
    #
    ## Dest unreachable
    ### from/to Internet
    $IPC -A input -p icmp --icmp-type destination-unreachable -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type destination-unreachable -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
    ### from/to Lan
    $IPC -A input -p icmp --icmp-type destination-unreachable -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type destination-unreachable -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
    ### from/to Peer Lan
    $IPC -A input -p icmp --icmp-type destination-unreachable -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type destination-unreachable -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT
    #
    ## Source quench
    ### from/to Internet
    $IPC -A input -p icmp --icmp-type source-quench -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type source-quench -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
    ### from/to Lan
    $IPC -A input -p icmp --icmp-type source-quench -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type source-quench -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
    ### from/to Peer Lan
    $IPC -A input -p icmp --icmp-type source-quench -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type source-quench -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT
    #
    ## Parameter problem
    ### from/to Internet
    $IPC -A input -p icmp --icmp-type parameter-problem -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type parameter-problem -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
    ### from/to Lan
    $IPC -A input -p icmp --icmp-type parameter-problem -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type parameter-problem -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
    ### from/to Peer Lan
    $IPC -A input -p icmp --icmp-type parameter-problem -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type parameter-problem -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT
    #
    ## Time To Live exceeded
    ### from/to Internet
    $IPC -A input -p icmp --icmp-type time-exceeded -s $ANY -d $MY_EXT -i $EXT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type time-exceeded -s $MY_EXT -d $ANY -i $EXT_IF -j ACCEPT
    ### to Lan
    $IPC -A input -p icmp --icmp-type time-exceeded -s $ANY -d $MY_INT -i $INT_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type time-exceeded -s $MY_INT -d $ANY -i $INT_IF -j ACCEPT
    ### to Peer Lan
    $IPC -A input -p icmp --icmp-type time-exceeded -s $ANY -d $MY_INT -i $IPSEC_IF -j ACCEPT
    $IPC -A output -p icmp --icmp-type time-exceeded -s $MY_INT -d $ANY -i $IPSEC_IF -j ACCEPT

    # ICMP PINGs
    ## from Internet
    $IPC -A input -p icmp -s $ANY -d $MY_EXT --icmp-type echo-request  -i $EXT_IF -j ACCEPT
    $IPC -A output -p icmp -s $MY_EXT -d $ANY --icmp-type echo-reply  -i $EXT_IF -j ACCEPT
    ## from LAN
    $IPC -A input -p icmp -s $ANY -d $MY_INT --icmp-type echo-request -i $INT_IF -j ACCEPT
    $IPC -A output -p icmp -s $MY_INT -d $ANY --icmp-type echo-reply  -i $INT_IF -j ACCEPT
    ## from Peer LAN
    $IPC -A input -p icmp -s $ANY -d $MY_INT --icmp-type echo-request -i $IPSEC_IF -j ACCEPT
    $IPC -A output -p icmp -s $MY_INT -d $ANY --icmp-type echo-reply  -i $IPSEC_IF -j ACCEPT

    # SSH
    ## from SSH_PEER_HOST
    $IPC -A input -p tcp -s $SSH_PEER_HOST -d $MY_EXT 22 -i $EXT_IF -j ACCEPT
    $IPC -A output -p tcp \! -y -s $MY_EXT 22 -d $SSH_PEER_HOST -i $EXT_IF -j ACCEPT
    ## to SSH_PEER_HOST
    $IPC -A input -p tcp \! -y -s $SSH_PEER_HOST 22 -d $MY_EXT -i $EXT_IF -j ACCEPT
    $IPC -A output -p tcp -s $MY_EXT -d $SSH_PEER_HOST 22 -i $EXT_IF -j ACCEPT
    ## from PEER
    $IPC -A input -p tcp -s $PEER_EXT -d $MY_EXT 22 -i $EXT_IF -j ACCEPT
    $IPC -A output -p tcp \! -y -s $MY_EXT 22 -d $PEER_EXT -i $EXT_IF -j ACCEPT
    ## to PEER
    $IPC -A input -p tcp \! -y -s $PEER_EXT 22 -d $MY_EXT -i $EXT_IF -j ACCEPT
    $IPC -A output -p tcp -s $MY_EXT -d $PEER_EXT 22 -i $EXT_IF -j ACCEPT

    # ipxtunnel
    $IPC -A input -p udp -s $PEER_INT 2005 -d $MY_INT 2005 -i $IPSEC_IF -j ACCEPT
    $IPC -A output -p udp -s $MY_INT 2005 -d $PEER_INT 2005 -i $IPSEC_IF -j ACCEPT

    ---------------- end of rc.firewall ----------------------

    To understand this we need to look on this scheme:

               ++-----------------------<----------------------------+
               || ipsec0                                             |
               \/                                                    |
     eth0  +--------+    /---------/ yes  /---------/ yes +-----------------------+
    ------>| INPUT  |-->/ ?local? /----->/ ?IPsec? /----->| decrypt & decapsulate |
     eth1  +--------+  /---------/      /---------/       +-----------------------+
                           || no            || no
                           \/               \/
                      +----------+      +---------+        +-------+
                      | routing  |      |  local  |        | local |
                      | decision |      | deliver |        | send  |
                      +----------+      +---------+        +-------+
                           ||                                 ||
                           \/                                 \/
                       +---------+                       +----------+
                       | forward |                       | routing  |
                       +---------+                       | decision |
                           ||                            +----------+
                           ||                                  ||
                           ++----------------<-----------------++
                           ||
                           \/
                       +--------+ eth0
                       | OUTPUT | eth1
                       +--------+ ipsec0
                           ||
                           \/
                       /---------/ yes +-----------------------+
                      / ?IPsec? /----->| encrypt & encapsulate |
                     /---------/       +-----------------------+
                          || no                    ||
                          ||                       ||
                          ||                       \/   eth0, eth1
                          ++-----------------------++-------------->

    This explain how a packet traverse TCP/IP stack in IPsec capable kernel.

    FIX ME, please, if there are any errors

    Test the new firewall now.

    Now about IPX. I tried 3 programs for tunneling IPX: tipxd, SIB and ipxtunnel

    tipxd didn't send packets.. :(
    SIB and ipxtunnel worked fine :)
    With ipxtunnel there was a little problem. In sources there are an error.

    --------------------- in main.c ------------------------
    <       bytes += p.len;
    ---
    >       bytes += len;
    --------------------------------------------------------

    After this FIX everything goes right...

    ------------------- /etc/ipxtunnel.conf ----------------
    port    2005
    remote  192.168.101.97    2005
    interface eth1
    --------------- end of /etc/ipxtunnel.conf -------------

    I use IPX tunnel between .1.1 and .2.10 so we don't need to encrypt nor
    authenticate encapsulated IPX packets, it is done with IPsec.

    If you don't wont to use iproute2 to change source IP you need to use SIB
    (it is able to bind local address) or establish tunnel between .0.1 and
    .0.10 (external IPs, you need to do encryption in the program, but it isn't
    strong).

    For now I'm using ipxtunnel.

    I think that's all for the moment. If there are any error, please e-mail me:
    poltorak@df.ru . It would be cool if someone puts the scheme of TCP/IP in
    kernel and firewall example on FreeS/WAN's manual pages.

    PoltoS