Rogue access points



  • More and more i'm facing the problem of rogue access points.
    A computer logs in on pfsense, the computer has an unsecured open AP connected to it,
    and so open sharing connection to the network.
    This really becomes an annoyance.
    Low timeout values for the captive portal isn't really an option for me.

    There's spoken a bit on this topic here :
    http://forum.pfsense.org/index.php/topic,9510.msg57542.html#msg57542

    sflow finds nat devices by looking at the TTL, haven't used it yet.
    http://www.sflow.org/detectNAT/

    Anyone an idea to fight rogue AP's ?



  • Well p0f has better heuristics to find NAT.
    But basically both programs base they're detection on assumption that X OS will mark their packets in a specific way.
    So really p0f is better suited but you can try and test your self.

    What you can do is intall p0f on pfSense and write a shell script that adds hosts, that p0f reports more than 30% as being behind NAT, to a table.
    If you can achive some kind of success i will take a look at integrating it on pfSense as time permits.



  • I tested p0f a bit, and actually does a very good job.
    I prefer to set the threshhold to 33%, cause i had a few false positives with the VER flag, dunno why yet.
    Maybe there is something wrong in my network ? have a bunch of wrt54g's with tomato.

    start p0f with : (add -d to start in deamon mode), (xl1 is my opt1 interface)
    p0f -i xl1 -MKU -T 33 -o /var/log/p0f.txt

    Shell script for cleaning output :

    
    awk < /var/log/p0f.txt '{gsub(/[:]/, ""); printf"\n" $9}' | awk '! a[$0]++' > /var/log/p0f.final
    
    

    I don't have much experience with shell scripting, so i hope this is most the most effecient way.
    Took me a while  ;)

    No i must fgure out a way to anchor it in the PF and rereading the file regulary.
    I think i must flush the file regulary since i'm using dhcp.

    edit : code was faulty.



  • The simplest method is adding a table to the ruleset and from the ruleset add the offending ips to the table.
    After that you add a cronjob to flush the table at intervals so you give hosts some chance to redeem :P.

    That is the simplest of the methods.

    The better is integrating the rest of p0f directly into pf as is the os detection one. But this needs some more time and dedication which is not in the most of priorities for me.

    Mostly i can give you advices on how to do that with simple scripting. Hope that comes to help at least.



  • Sure the best way to do this is integrating the masquerade detection of p0f.
    I'm sorry that i don't have the knowledge to do that, i'm completely self tought,
    and i'm not that far  ;)

    Ok, made a few changes to the script.
    It now writes directly to the p0f table.
    Add this script to a 15min ? cronjob.

    
    # First flush the table of blocked clients.
    pfctl -t p0f -Tflush 
    # Then add detected clients to the table.
    awk < /var/log/p0f.txt '{gsub(/[:]/, ""); printf"\n" $9}' | awk '! a[$0]++' | while read data;
     do
     pfctl -t p0f -Tadd $data 
    done
    # Last flush the p0f created file.
    cat /dev/null > /var/log/p0f.txt
    
    

    add to filter.inc

    
    # p0f
    table <p0f>block quick on xl1 from <p0f>to any label "p0f detected NAT clients"</p0f></p0f> 
    

    Now i want a http direct rule, so that blocked clients see why they are blocked,
    and don't come bother me.
    Dunno yet how i'm gonna do that.

    Mike



  • Now i want a http direct rule, so that blocked clients see why they are blocked,
    and don't come bother me.
    Dunno yet how i'm gonna do that.

    2 alternatives:
    1- host a simple page on pfSense itself with a very simple webserver or another instance of lighthttpd and add a rdr rule as
    rdr on $interface from <p0f>to any -> localhost port $otherwebserver

    2- use a route-to rule to redirect to another webserver in your reach/control
    pass in quick on $interface route-to ($interface_of_webserver $ip_of_server) from <p0f>to any keep state

    Try it and tell me how it goes.

    FWIW, the next step is trying to create a package of all this so at least other people can have something to use till the integration gets in the rules of pf. But a package should suffice for now.

    Ermal</p0f></p0f>



  • I forgot another thing.

    make the table declaration as

    table <p0f>persist

    Furthermore, you can save the offending ips one a file and make the table declaration as
    table <p0f>persist file $path_to_the_file/$file.ip.list

    so even if the box is rebooted the information is not lost.</p0f></p0f>



  • table <p0f>persist</p0f>

    check

    Furthermore, you can save the offending ips one a file and make the table declaration as
    table <p0f>persist file $path_to_the_file/$file.ip.list

    so even if the box is rebooted the information is not lost.</p0f>

    I first did this, but i guess it doesn't matter, as soon as the machine is booted up
    p0f detects and blocks the NAT device anyway.

    I'm having a bit of trouble creating a rdr rule.
    rdr on xl1 from <p0f>to any -> 10.20.7.1 port 81
    results in an error ?</p0f>



  • Are you sure your table decalration is befor the rdr rule?!



  • yes, even if i take the table out of the rule like :

    rdr on xl1 from any to any -> 10.20.7.1 port 81

    or whatever combo i allways get an error.

    Ok the error is :
    Rules must be in order: options, normalization, queueing, translation, filteringpfctl

    So my guess is the rule is inserted in the wrong place.



  • Oh :), you have to place it before any filter(pass/block) rule and after any traffic shaper rule.

    So the pf ruleset look like:
    1- set statements
    2- macro, table definitions
    3- QoS rules
    4- RDR/NAT/BINAT rules
    5- Filer rules

    If you have ftp-proxy active you should have rdr rules there, so place the rdr rule after those and you should be ok.



  • Ok, done,
    Right now im testing it in a live setup.

    I'll report back my findings soon.



  • Consider making this a package so you do not have to mackle with scripts next time.
    I will review/help/commit this package if at least half the work is done.



  • Thx for the support anyway!!!!!



  • I was away for a few days, but left the setup running, and seems to be very stable.
    Next i'm learning about creating packages, wich seems quite a task.
    I'll do my best to create this into a package, may take a while though.
    I'm still working on it !



  • Most of it is an xml file and an include doing verification and data saving.

    Find the simplest port copy over its files and it should be straight forward… :)



  • This seems like something (like flow data) that could be useful in the base system.  It's footprint is fairly small (although I'd need to look at cpu consumption).  Thoughts?

    nb



  • Yeah i though of writing a package for it as a tutorial and see if it has the audience to get in base.



  • I was in an accident and have been in the hospital for a while.
    I haven't got the time now to create a package.
    In a few weeks, i think i'm starting to work again,
    and hope to pick up on things like this. If there are people who are interested.
    I hope you understand.

    In the mean time i can give you my notes to get it all working manually.

    -install p0f
    -install shttpd
    -create a webpage for blocked clients.

    << create script for adding blocked ip's in /usr/local/bin/p0fcron.sh

    First flush the table of blocked clients.

    pfctl -t p0f -Tflush

    Then add new detected clients to the table.

    awk < /var/log/p0f.txt '{gsub(/[:]/, ""); printf"\n" $9}' | awk '! a[$0]++' |while read data; do pfctl -t p0f -Tadd $data
    done

    Last flush the p0f created file.

    cat /dev/null > /var/log/p0f.txt

    << add cronjob to /conf/config.xml adding and deleting ip's every 10 minutes
    <task_name>p0f</task_name>
    <minute>/10</minute>
    <hour>
    </hour>
    <mday></mday>
    <month>
    </month>
    <wday>*</wday>
    <who>root</who>
    <command></command>/usr/local/bin/p0fcron.sh

    << filter: add rederict rule for blocked ip's in /etc/inc/filter.inc
    $natrules .= "# p0f\n";
    $natrules .= "table <p0f>persist\n";
    $natrules .= "rdr on xl1 proto tcp from <p0f>to any -> 10.20.7.1 port 81\n";

    << create startup script /usr/local/etc/rc.d/p0f.sh
    << -i xl1 is the interface to listen on
    << -T is the threshold
    chmod 0755


    #!/bin/sh
    echo -n ' p0f '

    case "$1" in
    start)
            /usr/local/bin/p0f -i xl1 -MKU -T 33 -d -o /var/log/p0f.txt
            ;;
    stop)
            kill -9 cat /var/run/p0f.pid
            ;;
    *)

    esac

    exit 0

    << create startup script /usr/local/etc/rc.d/p0f.sh
    chmod 0755


    #!/bin/sh
    echo -n ' shttpd '

    case "$1" in
    start)
            /usr/local/bin/shttpd -p 81 -d /usr/local/www/p0f -l /var/log/shttpd.log
            ;;
    stop)
            kill -9 cat /var/run/shttpd.pid
            ;;
    *)

    esac

    exit 0</p0f></p0f>


Locked