|
How I Secured my FreeBSD System by che guevara of the phonerangers che@cheggy.net che@phonerangers.org www.cheggy.net www.phonerangers.org I'm really paranoid. I am also a geek. I got a kick out of doing this, and feel like sharing. This is how I made my FreeBSD system as secure to the outside world as I could. I still run X, Netscape 4.5, etc. on my system, so it isn't as secure as it could be. If I made as secure as possible, I wouldn't be able to use it and that would suck. Well, my paranoia paid off. Two seperate times my computer has come under what I considered attack. The first time it came from some big corporation's server. It was an attempt to use Back Orifice on me (which is kinda stupid cause i run freebsd, bo only works on windows!). The second was more interesting. Somebody portscanned me, both TCP/UDP, about ten minutes after I finger'd them. Strange, retaliating to an unagressive finger with a portscan. I noticed the portscan because of the unique noise my hard drive made as it wrote over thirteen hundred log entries to disk. Well, this person found no ports open on my machine, and I found 27 open on his (without even trying UDP!). He left his SMTP port wide open.... So I sent him some mail asking him to cut it out. Well, those were the times my security actually stopped attacks against my machine. The outermost layer of my security is a firewall. Your basic, everyday packet filtering chunk of kernel code. I want to be able to talk to the outside world, but I don't want anybody being able to talk to me. Since I have no need for other computers to be able to initiate a connection to my machine, as few as possible can. First the firewall allows everything to pass internally . This is accomplished with: ipfw add 1000 pass all from any to any via lo0 I need my DNS, because being able to resolve hostnames is a good thing. I have to use four lines here, two for my primary DNS server and two for my secondary. So: ipfw add 1010 pass udp from {DNS server's IP} to {My IP} ipfw add 1011 pass udp from {My IP} to {DNS server's IP} ipfw add 1015 pass udp from {DNS server's IP} to {My IP} ipfw add 1016 pass udp from {My IP} to {DNS server's IP} I want to be able to connect outwards, but I don't want any connections coming in. I enable out going TCP setup, and disable incoming TCP setup. I also have a rule passing established TCP data, so that once I get my connection setup I can get subsequent data in and out of my system. The setup denial rule is global, because it comes after the out going setup rule and so the first one matches. ipfw add 1020 pass tcp from {My IP} to any setup ipfw add 1030 deny log tcp from any to any setup ipfw add 1040 pass tcp from any to any established Next I pass all ICMP, which is really only so I can ping. ipfw add 1050 pass icmp from any to any Finally, everything else gets denied. ipfw add 2000 deny log ip from any to any I have a dynamic IP dialup connection to the outside world, and so I need to be able to change {My IP} every time I dialup and initialize my firewall. I have written two simple scripts to get my IP out of my routing table and then sets my firewall rules accordingly. The first of these scripts gets my IP and then calls the second. It is named getip, and reads: #!/bin/sh netstat -rn | grep {Terminal server's IP} | grep UH | awk '{print $2}' | xargs -t /root/firewall_rules This script lists the contents of my routing table, finds the route leading to my IP, and then sticks my IP in as the first argument to /root/firewall_rules, the second script. This script reads: #!/bin/sh ipfw -f flush ipfw add 1000 pass all from any to any via lo0 ipfw add 1010 pass udp from {DNS server's IP} to $1 ... This allows me to dynamically initialize my firewall according to the new IP which I get assigned every time I dialup. After my firewall, any intruder will have to deal with tcp_wrappers. My wrapper's configuration is simple, is contained in /usr/local/etc/hosts.deny, and reads: ALL : ALL EXCEPT localhost This denies all hosts except localhost access to all daemons. Alternatively, if an intruder wishes to access any port which is not covered by inetd, they must deal with Abacus Sentry. I run Sentry in both standard TCP and UDP modes, and cover the following ports: TCP: 1,7,9,11,15,25,70,79,80,109,110,111,119,138,139, 143,512,513,514 515,540,2000,2001,4000,4001,6001,6667,32771,32772,32773,32774,31337,49724 UDP: 1,7,9,25,66,67,68,69,111,137,138,161,162,474,513,517,518, 635,640,641,666,700,2049,32770,32771,32772,32773,32774 This provides extensive screening of often targeted ports. As well as running sentry, I run fakebo on UDP port 31337. This program mimics a Back Orifice server, and will treat all recieved commands as if they were successfully executed. I have also taken some other miscelaneous precautions. Behind every port on my computer I have set my kernel to log packets that were sent to a given port but not recieved by any program bound to that port. I have done this by changing net.inet.{tcp|udp}.log_in_vain to 1. A useful side effect of this is that it catches TCP SYN stealth scans that hit unbound ports of my computer. I do not run sendmail or any other MTA. I have good passwords (as in, contain spaces, variable capitalization, etc.). I read my logs for sign of intrusion. I listen to my hard drive for sign of intrusion. Yes, this is true. The noise of all those log entries getting written to disk when my security picks up on the fact that I am getting port scanned is (in my experience) unique, and since I have a loud hard drive I can hear it. Heehee, I love being a geek. Other sites: http://www.freebsd.org/ http://www.psionic.com/tools/sentry/ ftp://ftp.porcupine.org/pub/security/ http://www.insecure.org/nmap