# FreeBSD 10.1 server security question



## hockey97 (Jun 3, 2015)

Ok, I finally got everything updated from FreeBSD 8.4 to FreeBSD 10.1.
While doing the upgrade my network been attacked by DDOS and brute force attacks. I had to shutdown my servers.

I used ftpd in the past and was currently using it. Someone on here advised not to use it since it's not secure. I was advised to use sftpd and install ssh. I got ssh installed already. I was told to use that with a firewall and fail2ban. 

The thing is that I don't need to remotely use my server. In the same building I use other computers to upload code to my website via ftp. On my routers for internal networks. I have the router only accept my external ips to connect. I have a ip whitelist.

I would feel more comfortable if I have some kind of whitelist for any ftp access they must have that ip address and mac address. I don't know if this is possible?

So, my question here is what is the best towards preventing hackers get access to your servers?  Why does fail2ban work? I am on a small network and to me the fail2ban I don't think it can stop ddos attacks?

What are the safety measures for apache, mysql, posfix  and I use webmin to help administrate the servers. I just don't want to be compromised. 

What do you guys do if under a DDOS attack? I recently reported the attacks to the persons ip address. Their ISP didn't do anything at all. I was told online the only thing is to report it to the police.

How does one stop these attacks? Or at least report it in legal matters?


----------



## Remington (Jun 3, 2015)

You can't stop DDoS attacks as they come from multiple sources at the same time.  You will have to use a provider that specialize in anti-DDoS attacks such as Cloudflare.  Some data centers may have this feature for their clients to prevent their client's server being overloaded, flooded and charged for the unwanted internet traffic.  Other than that, there's not much you can do to prevent it.  Fail2ban does help by monitoring the logs and add attacker's IP to PF's firewall but your server still will have unwanted traffic hitting your ethernet card.

I would suggest you to change your host's SSH port to something different than 22.  Most attackers are autobots and port 22 is the most common target.  You'll notice your log file will be small this way if you change your port number.

You should look into using suphp and suhosin for additional PHP protections (and I don't use this).

You can also use PHP's open_basedir, disabile_functions and safemode (and I use this instead).

Here is an example:


```
disable_functions = chgrp, copy, diskfreespace, disk_free_space, disk_total_space, dl, escapeshellarg, escapeshellcmd, exec, getmyuid, getmypid, getrusage, get_current_use, highlight_file, ini_alter, ini_get_all, ini_restore, leak, link, mysql_list_dbs, passthru, pclose, pfsockopen, php_uname, popen, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, setlimit, set_time_limit, shell_exec, show_source, sscanf, system, tempnam

open_basedir = /home/user/:/var/www/html:/tmp (plus some personal paths for some special reasons).
```

If you have some problems with PHP code being denied by the disable_functions, you can decide to modify line if you know if it's safe to make changes.


----------



## hockey97 (Jun 3, 2015)

Thanks for the response. Right now I setup ipfw(8) on my freebsd FreeBSD 10.1 server.
I created a custom script / rule but it looks like it's not working. The firewall is using it's default settings by closing all ports.
I followed online tutorials and written the syntax like this:


```
ipfw -q add 10 allow tcp from external_ip to any 22 out
```
Is that the proper code syntax?

The external IP is the IP address that connects to my server. This example is port 22.

I will take your advice and change the port.

I would appreciate it if someone can explain what is needed for the ipfw script in order for it to run.

Also what permissions does it need? I have looked at the hand book and it gave examples but still wasn't too clear and I haven't seen anywhere that says what permissions the script needs.

Does it need `#!/bin/sh` that at the top?


----------



## Remington (Jun 3, 2015)

I'm not an expert with IPFW.  I'm more of a PF guy so I'll let someone else chime in.

As far as I know #!/bin/sh isn't needed for IPFW script and neither does PF.  Permission should be 755 and root:wheel.


----------



## kpa (Jun 3, 2015)

The ipfw(4) rule file is a shell script so having the shebang at the start is not completely wrong. However, it is run with /bin/sh from /etc/rc.d/ipfw if you set firewall_script correctly in rc.conf(5) so the shebang is not actually needed unless you want to run the script yourself from shell.


----------



## von_Gaden (Jun 3, 2015)

I'm one of (still) keen IPFW users and I'll share a part of my script. Note that I'm probably using an older syntax but it works fine and that is one of the great advantages of FreeBSD!
As for the DDoS attacks nothing can stop them and fail2ban is more likely to make you just feel better but it will not help a lot. My experience shows that bringing a FreeBSD server to denial of service (I speak about well configured one with enough resources) is not an easy task, is it?

Here is a sample based on my /etc/rc.firewall. The machine acts as gateway and performs nat

```
#!/bin/sh

fwcmd="/sbin/ipfw -q"

ext_ip="1.2.3.4"
int_if="re0"
ext_if="re1"
internal_net="{ 10.11.12.0/24 }"

spoofer_ip="{ 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 or 127.0.0.0/8 or 0.0.0.0/8 or 224.0.0.0/4 or 240.0.0.0/4 }"
ms_ports="67,68,135,137,138,139,445,2504,42,102,1500,2500,3389,1801,2101,2103,210,3527,1645,1812,1646,1813,69,560,1234,4444,3551"
bad_ports="9996,5554,6777"

# Flush all rules
${fwcmd} -f flush
${fwcmd} -f pipe flush

# Loopback interface
${fwcmd} add pass all from any to any via lo0

${fwcmd} add deny ip from any to any not verrevpath in
${fwcmd} add deny ip from any to any ${bad_ports} in

# LAN network interface  ${int_if}
${fwcmd} add pass all from ${internal_net} to ${internal_net} via ${int_if}
# some limitations for external traffic here
# ...
${fwcmd} add pass all from ${internal_net} to any in recv ${int_if}
${fwcmd} add pass all from any to ${internal_net} out xmit ${int_if}
${fwcmd} add deny all from any to any via ${int_if}

# External interface ext_if
# Recv
# Anti-Spoofing
${fwcmd} add deny all from ${spoofer_ip} to any in recv ${ext_if}

# Block NetBios & other MS-specific services
${fwcmd} add deny all from any to any ${ms_ports} via ${ext_if}

${fwcmd} add deny all from any to not ${ext_ip} in recv ${ext_if}

# NAT
${fwcmd} add divert natd all from any to ${ext_ip} in recv ${ext_if}

${fwcmd} add pass all from any to ${ext_ip} in recv ${ext_if}
${fwcmd} add pass all from any to ${internal_net} in recv ${ext_if}

${fwcmd} add deny all from any to any in recv ${ext_if}

# External interface ext_if
# Xmit
# Anti-Spoofing
${fwcmd} add deny all from any to ${spoofer_ip} out xmit ${ext_if}

# NAT
${fwcmd} add divert natd all from ${internal_net} to any out xmit ${ext_if}

${fwcmd} add pass all from ${ext_ip} to any out xmit ${ext_if}
${fwcmd} add deny all from any to any out xmit ${ext_if}

# Deny all
${fwcmd} add deny all from any to any
```
If you use GENERIC kernel you'll need this in /boot/loader.conf:

```
ipfw_load="YES"
net.inet.ip.fw.default_to_accept="1" #some people hate this
ipdivert_load="YES"
dummynet_load="YES" #if you use pipes
```
As you can see this is not the state-of-art but it's simple and working. I hope you'll find it helpful somehow.
Considering security: are tools as webmin secure enough? Is bringing root access (mostly) to web a good idea? Yes, it's easy and colorful but...


----------



## Jeckt (Jun 3, 2015)

hockey97 said:


> ```
> ipfw -q add 10 allow tcp from external_ip to any 22 out
> ```
> Is that the proper code syntax?




The syntax is correct, but I think you have the direction wrong;

```
ipfw add 10 allow tcp from $ip_address to me 22 in
```
This requires you allow outgoing packets from the server. A fairly lax way to do it is:

```
ipfw add 56780 allow all from me to any
```
Also, stuff like DNS and (maybe) icmp need allowances as well.


----------



## hockey97 (Jun 4, 2015)

Jeckt said:


> The syntax is correct, but I think you have the direction wrong;
> 
> ```
> ipfw add 10 allow tcp from $ip_address to me 22 in
> ...




Do I have to use me? I used any to not be specific since I have 2 ip addresses config with my server.

The allow all from me. I want to restrict it. I just need my webserver and mail server to communicate to the internet. I don't need mysql database to be accessed by the internet.  Just expose the mail server and web server to the internet. The ssh server for sftpd should be strictly for only the ip addresses that I own. 

I don't want my server to respond to portscans. 

Why would I need DNS? On the server I can surf the web find. It's not just when ipfw runs. Every port on my server is blocked. I turned it off and checked my servers and they're running with no errors. Yet, when I pick it back on I get errors like refused connection. 

Do you think I need that -q in the rule? 

The code I posted in the previous post. Shouldn't it work?  My point is that when the firewall is on. I get all ports closed. 

I have the same format but at the end instead of in I put out. I put a rule for a network block and rules for certain external ip addresses. I allow those certain ips to connect via that port.

However, the firewall still blocks all ports.


----------



## hockey97 (Jun 4, 2015)

I decided to run this command: `ipfw list` It listed all the rules. I notice at the last line it says deny ip from any to any. I see all my lines and at the bottom I see that line which blocks everything.  I search online and found that this was the default rule. I don't know how to prevent this from running?  In /etc/rc.conf I have it set  firewall_enable ="YES" and firewall_script="path_to_file". 

How can I prevent that rule from loading up?  I even restarted ipfw and ran that command again and got the same exact list. This rule is at the bottom. I read online that it should go away once you specified firewall_script in /etc/rc.conf. I had this set like that and still it shows up.


----------



## hockey97 (Jun 4, 2015)

hockey97 said:


> I decided to run this command: `ipfw list` It listed all the rules. I notice at the last line it says deny ip from any to any. I see all my lines and at the bottom I see that line which blocks everything.  I search online and found that this was the default rule. I don't know how to prevent this from running?  In /etc/rc.conf I have it set  firewall_enable ="YES" and firewall_script="path_to_file".
> 
> How can I prevent that rule from loading up?  I even restarted ipfw and ran that command again and got the same exact list. This rule is at the bottom. I read online that it should go away once you specified firewall_script in /etc/rc.conf. I had this set like that and still it shows up.


Never mind figured it out. I left out keywords setup keep-state


----------



## Jeckt (Jun 4, 2015)

hockey97 said:


> Do I have to use me? I used any to not be specific since I have 2 ip addresses config with my server.
> 
> I don't want my server to respond to portscans.
> 
> ...



It sounds like you got it working, but to answer your question, you do not need to use "me", however the more specific you are the better because it leaves no room for ambiguity. You can see in von_Gaden's script he's very specific about traffic.  In ipfw "me" means all of the server's addresses, and if no interface is specified basically means all interfaces that the server considers itself (including the loopback).

"-q" just means quiet. When you add a rule to the firewall, it is echoed back by default which some people don't like.

You need outgoing DNS for your mail server to look up hostnames.

With a stateful firewall you can get away with a few rules. Make sure the server can communicate with itself over the loopback interface (lo0)


----------



## hockey97 (Jun 5, 2015)

Jeckt said:


> It sounds like you got it working, but to answer your question, you do not need to use "me", however the more specific you are the better because it leaves no room for ambiguity. You can see in von_Gaden's script he's very specific about traffic.  In ipfw "me" means all of the server's addresses, and if no interface is specified basically means all interfaces that the server considers itself (including the loopback).
> 
> "-q" just means quiet. When you add a rule to the firewall, it is echoed back by default which some people don't like.
> 
> ...



Ya, I understood what you're saying. I spent 3 days playing around with the rules. I had any but now switched to me. I then had a deny all rule for MySQL. I quickly when going to my website got my SQL printed out on screen showing the connection information with a message saying permission denied. I realized then I pretty much blocked everything and quickly understood I needed at least localhost to be permitted. So, I added 2 rules. One on top that approves just localhost to connect to MySQL. The rule after that said deny all. I read in the handbook that the rules in order from top to bottom The rules above runs first. So, in my case for MySQL if not localhost then you will match the 2nd rule below which will deny you access.

I really wished I did this years ago. I recently been hit by a few hackers in the U.S that failed to get in. I then got a large attack from china. Then saw on the local news that the Chinese hacked the U.S government recently.

Is there any stick on FreeBSD.org? That will give us updated information on security risks and flaws?

I remember OpenSSL's Heartbleed security flaw. I updated that quickly as soon as I heard the news.


----------



## juiced (Jun 5, 2015)

A few things I would do.

-Don't use ftp at all, completely uninstall it.
-Use SSH and as others have said configure it to run on a different port.
-Limit connectivity to the new ssh port to your ip address or your IP subnet via the firewall.
-Use the PF firewall - imo its more easily tunable, more readable and just sexy.
-Set the state type then seriously limit the state timeouts.
-Use a block all rule set with PF. Allow only exactly what you need and nothing else.
-After doing the firewall setup use security/nmap or the GUI security/zenmap and scan your sever. Make sure everything other than what you need is closed. And that there's no ports held open by some random service.
-Don't use Apache - its a bloated under performing pig. - Try something like Nginx.
-Read up on using Jails.
-Fail2Ban mainly only stops bots. Anyone that wants in->will bypass it.
-Don't leave webmin running when not in use. SSH in and turn it on when needed then shut it down again. And change the webmin port. You could also limit access to the webmin port to your ip or subnet - like the ssh port.

By the sound of your post it seems like its a single ip DDoS'ing you - which is rare, but if that's really the case it shouldn't be all that bad unless its from a massive box @ 1GB+ connection. I'm guessing whats failing is apache bloating up from all the connections or the cms doing loads of database calls. Nginx + well tuned fcgi php can help with the front end and CMS depending, some form of caching could help with the db. I'm a fan of the nginx fastcgi_cache using tmpfs for cache storage. But if your site is dynamic fastcgi_cache can be problematic.
-However if the DDoS is massive and from multiple sources you're SOL.

What I would do is setup a VM 'virtual machine' that has the exact same setup/install of your server. -Same settings, ram amount, cpu cores, server software, database, firewall ect. Then start testing in that.

There's other things that can be done via sysctl and elsewhere. But they're not something I would do in a live environment. Setup a testing VM and take it from there. 

-GL


----------



## Remington (Jun 5, 2015)

Juiced.. I did exactly what you did and its all true.  One more thing about DDoS attacks from multiple sources, contact the data center and ask them to add anti-DDoS feature if they have it or use Cloudflare service.  They have the resources to block out DDoS attacks and allow regular traffic to the server without overloading the server or being charged for unwanted traffic to the server.  I also have my servers behind pfSense box and it helps a lot.

PF and IPFW are both equally good but I think PF rules are easier to write.


----------



## juiced (Jun 5, 2015)

I agree Remington. -If your host offers DDoS protection and it's not super expensive use it.

Cloudflare can be helpful too but I've had bad experiences with them mass blocking IP's for extended periods of time. I don't personally use them. But many do and love the service.

Normally I just limit connections per IP via Nginx, tweak PF state timeouts, use PHP caching, use fastcgi caching and tweak MySQL.

I also make heavy use of tmpfs(5) for things like logging etc. Logging failed connections via the firewall during a DDoS can be painful. Tmpfs can help limit it 'for a while' but normally I'll disable logging when under DDoS then temporarily use proxy pass for PF. Unfortunately its all really situational and sometimes you can't even access the machine. So DDoS protection from the host is really the only option.


----------

