Premium Shogun 4585 Posted February 4, 2014 Premium Share Posted February 4, 2014 (edited) Update April 2020 I have modified the rules to allow ipv6 connections, and added some comments. Update: January 2021 New more exhaustive and optimized config, and more explanations Hello, As I had just posted the file without any explanation of it, which is not really useful unless you are already familiar with pf, I have added a little tutorial. Here is a sample pf.conf file that you can use as a base to create your own for your FreeBSD server. It assumes you are not using UDP as the original client does. Preliminary steps Add the following to /etc/rc.conf to enable pf. It will enable the pf firewall on boot and log blocked packets to /var/log/pflog. This is not a text file but a pcap file that can be opened using tcpdump -r /var/log/pflog (followed by any other flags you may want to use). For a good tcpdump cheatsheet check https://danielmiessler.com/study/tcpdump/ The second part is ip6addrctl which attempts to use ipv4 addresses instead of ipv6, since the game does not support ipv4. # Packet Filter pf_enable="YES" pf_rules="/etc/pf.conf" pflog_enable="YES" pflog_logfile="/var/log/pflog" # Prefer ipv4 when available ip6addrctl_enable="YES" ip6addrctl_verbose="NO" ip6addrctl_policy="ipv4_prefer" Firewalling The configuration file further below must be save as /etc/pf.conf (be aware the default location for pf rules may not be here anymore; if you used my rc.conf above that should be no issue). Before attempting to use it, make sure to change everything that is between brackets. You can find out the relevant parameters with the ifconfig command on FreeBSD. root@godzilla:/home/www $ ifconfig igb0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=e53fbb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,WOL_UCAST,WOL_MCAST,WOL_MAGIC,VLAN_HWFILTER,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6> ether d0:40:19:d5:e3:69 inet 57.93.137.82 netmask 0xffffff00 broadcast 57.93.137.255 inet 57.93.114.128 netmask 0xffffffff broadcast 57.93.114.128 inet6 fe80::d110:99ff:fec4:e469%igb0 prefixlen 64 scopeid 0x1 inet6 2001:27d0:119:1872:: prefixlen 64 media: Ethernet autoselect (10Gbase-T <full-duplex>) status: active nd6 options=8063<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL,NO_RADR,DEFAULTIF> [int] is name of your external interface (ix0, igb0, etc...). It's the first thing that appears below ifconfig. [primary_ip] is the one after the first "inet" (in this case 57.93.137.82) [game_ip] is the one after the second "inet" (in this case 57.93.114.128) [ipv6] is the one you see after the second inet6. Finally, edit the service_ports, game_ports and auth_ports with the ports you want to open for administrative tasks and for the game, separated by commas. At the very least, add your SSH port to service_ports or you won't be able to connect to your machine. Why have 2 IPs? Easy: you cannot change your primary IP. If a DDoS brings down your machine, you can block all traffic to your secondary IP while working on protective measures through your primary IP. If all else fails you could even bind your game, or whatever you are running, to a third IP and hope the attacker doesn't notice (yeah sounds dumb but so is the people doing that stuff!). If you just have one IP, you may not be able to access your server at all. So the idea is that you access SSH and other administrative stuff through the primary IP while any public facing services go through a secondary IP or several of them. The OVH firewall can help you closing unneeded ports. Closing UDP there is also a very good idea if you don't need it - if you get a UDP flood bigger than your bandwidth, PF is not going to help you. When inbound traffic saturates your link, it's already too late to do anything at the OS level - it must be done by a hardware firewall or mitigation system such as the one provided in the OVH Panel (IP menu). If you prefer to use just one IP, you can just enter the same one as both primary and secondary. Or, if you want to do it properly, remove all references to $game_ip throughout the file. Also, if you don't have ipv6 set up, comment out (#) or remove every line that mentions "inet6". And finally, there is a file named /var/db/trusted_hosts which is a simple text file you can create with ee or vi. This is where you can add your own IP, or the IP address of other servers such as your webserver that you want to give full access without going through the rules. Write one IP per line, and be aware that your own IP could change so don't rely on this to give you access permanently - more like a fallback in case you make a mistake. ext_if="[int]" set skip on lo0 set block-policy drop set loginterface $ext_if primary_ip="[x.x.x.x]" game_ip="[x.x.x.x]" ipv6="[x:x:x::]" icmp_types = "{ echorep, unreach, squench, echoreq, timex, paramprob }" icmp6_types = "{ unreach, toobig, timex, paramprob, echoreq, echorep, neighbradv, neighbrsol, routeradv, routersol }" table <trusted_hosts> persist file "/var/db/trusted_hosts" table <bad_hosts> persist scrub in on $ext_if all fragment reassemble martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \ 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, \ 0.0.0.0/8, 240.0.0.0/4 255.255.255.255/32 \ ::/128 ::1/128 ::ffff:0:0/96 ::/96 100::/64 \ 2001:10::/28 2001:db8::/32 fc00::/7 fe80::/10 \ fec0::/10 ff00::/8 }" service_ports="{ 21, 80, 443 }" # Game game_ports="{ 24000, 24001, 24002, 24010, 24011, 24099 }" auth_ports="{ 28000 }" ## Set default policy ## block return in log all pass in quick from <trusted_hosts> # Drop all Non-Routable Addresses block drop in quick on $ext_if from $martians to any block drop out quick on $ext_if from any to $martians block in quick from <bad_hosts> ## Blocking spoofed packets antispoof quick for $ext_if pass proto tcp from any to any port $service_ports pass inet proto icmp icmp-type echoreq # Allow essential outgoing traffic pass out on $ext_if inet proto { tcp, udp, icmp } pass out on $ext_if inet6 proto { tcp, udp, icmp6 } pass out on $ext_if inet6 proto icmp6 all icmp6-type echoreq keep state # Game, we do not ratelimit here pass proto tcp from any to any port $game_ports pass proto tcp from any to $ipv6 port $game_ports # Auth pass in quick proto tcp to $game_ip port $auth_ports keep state (max-src-conn 32, max-src-conn-rate 16/3, overload <bad_hosts> flush global) pass in quick proto tcp to $ipv6 port $auth_ports keep state (max-src-conn 32, max-src-conn-rate 16/3, overload <bad_hosts> flush global) ## allow icmp6 for getting address using IPv6 autoconfiguration from router pass inet6 proto ipv6-icmp all icmp6-type routeradv pass inet6 proto ipv6-icmp all icmp6-type routersol ## allow icmp6 for getting neighbor addresses pass inet6 proto ipv6-icmp all icmp6-type neighbradv pass inet6 proto ipv6-icmp all icmp6-type neighbrsol ## allow icmp6 echo, not required, but sometimes nice pass in inet6 proto ipv6-icmp all icmp6-type echoreq ## pass icmp-types: unreachable, time exceeded, parameter problem pass in inet6 proto ipv6-icmp all icmp6-type {1 3 4} Using pfctl pfctl as its name implies is a tool to control pf. There are plenty of cheatsheets online, but here's the most basic stuff: pfctl -e Enable pf (WARNING will drop all connections including yours) pfctl -d Disable pf (may have the same effect) pfctl -f /etc/pf.conf Reload rules (may drop connectionds as well but usually it shouldn't) pfctl -sa Show all status pfctl -t bad_hosts -T flush Flush the bad_hosts table (effectively unbanning all IPs banned by the ruleset) pfctl -t bad_hosts -T show Show all the IPs banned so far Using tcpdump with pf You may watch the packets being blocked in realtime by using tcpdump on the pflog0 interface: tcpdump -i pflog0 -ttt -n -e Or instead show the previously logged ones. You may probably want to filter the output with either grep or further tcpdump flags. tcpdump -r /var/log/pflog -n -e Extras Here are some sysctl tunings that may help with certain DDoS attacks. You cann add them at the end of /etc/sysctl.conf and then type service sysctl restart at the command prompt to activate those. I don't recommend doing so unless you're being attacked though. That's why I have commented them out - remove all the # if you actually need them at some point. #net.inet.tcp.syncookies=1 #net.inet.tcp.syncache.rexmtlimit=0 #net.inet.ip.check_interface=1 # verify packet arrives on correct interface (default 0) #net.inet.ip.process_options=0 # IP options in the incoming packets will be ignored (default 1) #net.inet.ip.redirect=0 # do not send IP redirects (default 1) #net.inet.ip.accept_sourceroute=0 # drop source routed packets since they can not be trusted (default 0) #net.inet.ip.sourceroute=0 # if source routed packets are accepted the route data is ignored (default 0) #net.inet.icmp.bmcastecho=0 # do not respond to ICMP packets sent to IP broadcast addresses (default 0) #net.inet.icmp.maskfake=0 # do not fake reply to ICMP Address Mask Request packets (default 0) #net.inet.icmp.maskrepl=0 # replies are not sent for ICMP address mask requests (default 0) #net.inet.icmp.log_redirect=0 # do not log redirected ICMP packet attempts (default 0) #net.inet.icmp.drop_redirect=1 # no redirected ICMP packets (default 0) #net.inet.icmp.icmplim_output=1 # show "Limiting open port RST response" messages (default 1) #net.inet.tcp.always_keepalive=0 # tcp keep alive detection for dead peers, can be spoofed (default 1) #net.inet.tcp.drop_synfin=1 # SYN/FIN packets get dropped on initial connection (default 0) #net.inet.tcp.fast_finwait2_recycle=1 # recycle FIN/WAIT states quickly (helps against DoS, but may cause false RST) (default 0) #net.inet.tcp.icmp_may_rst=0 # icmp may not send RST to avoid spoofed icmp/udp floods (default 1) #net.inet.tcp.msl=15000 # 15s maximum segment life waiting for an ACK in reply to a SYN-ACK or FIN-ACK (default 30000) #net.inet.tcp.path_mtu_discovery=0 # disable MTU discovery since most ICMP type 3 packets are dropped by others (default 1) #net.inet.tcp.rfc3042=0 # disable limited transmit mechanism which can slow burst transmissions (default 1) #net.inet.tcp.sack.enable=1 # TCP Selective Acknowledgments are needed for high throughput (default 1) #net.inet.udp.blackhole=1 # drop udp packets destined for closed sockets (default 0) #net.inet.tcp.blackhole=2 # drop tcp packets destined for closed ports (default 0) Disclaimer I am by no means an expert in the subject, and I have just a vague idea about what many of the settings are actually doing. The above stuff has been helpful in real life situations, having been through literally hundreds of DDoS attacks. Be aware that pf may lock you out of your own system, and you may need to use IPMI/KVM to gain access again by disabling pf in /etc/rc.conf and then fixing the errors. Use at your own risk. PS: Here is a very good writeup about modern DDoS attacks: https://www.imperva.com/docs/DS_Incapsula_The_Top_10_DDoS_Attack_Trends_ebook.pdf Edited January 26, 2021 by Shogun 3 6 2 20 Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted February 14, 2014 Author Premium Share Posted February 14, 2014 I have added a little explanation of the file on the first post. Here's also a PF Quickstart Guide To enable pf on your server, you can follow these steps after you have saved the pf.conf file. Be careful not to lock yourself out with wrong firewall rules, it's a good idea to add your own IP address to trusted_hosts if you are unsure of your changes. kldload pf pfctl -f /etc/pf.conf If everything is correct it should display this: No ALTQ support in kernel ALTQ related functions disabled To load pf on every boot add this line to /etc/rc.conf: pf_enable="YES" Managing the IP ban list To show all banned IPs: pfctl -t abusive_hosts -T show To ban an IP: pfctl -t abusive_hosts -T add 8.8.8.8 To unban an IP: pfctl -t abusive_hosts -T delete 8.8.8.8 To unban all IPs: pfctl -t abusive_hosts -T flush 2 Link to comment Share on other sites More sharing options...
Mr.Xhater 1 Posted February 22, 2014 Share Posted February 22, 2014 And the port 15000 ? Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted February 22, 2014 Author Premium Share Posted February 22, 2014 And the port 15000 ? Port 15000 should never be publicly open! Only the game cores need to connect to it, not your users. In fact it's a security risk as anybody can create an auth server which connects to your db core and login any account they want on your server. Link to comment Share on other sites More sharing options...
Rumor 2603 Posted February 22, 2014 Share Posted February 22, 2014 And the port 15000 ? I like to block the P2P ports and port 15000 from outside access Link to comment Share on other sites More sharing options...
callmax 227 Posted February 22, 2014 Share Posted February 22, 2014 pass in on $ext_if proto {tcp,udp} to any port $game_ports flags S/SA keep state (max-src-conn 30, max-src-conn-rate 15/5, overload <abusive_hosts> flush) i think to know that the rule had to be like this pass in on $ext_if proto {tcp,udp} to any port $game_ports flags S/SA keep state (source-track rule, max-src-conn 30, max-src-conn-rate 15/5, overload <abusive_hosts> flush) I'm not completly sure, but i think "max-src-conn" and "conn-rate" can't take affect without sourcetrackrule Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted February 23, 2014 Author Premium Share Posted February 23, 2014 According to this "Both of these options automatically invoke the source-track rule option and are incompatible with source-track global." 1 Link to comment Share on other sites More sharing options...
Evor 72 Posted February 23, 2014 Share Posted February 23, 2014 So i have a question. How can i approach this task. I want to reject all conections wich are for more than 3 seconds synchronizing? Or these connections which are lagging for more than 15sec? Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted February 24, 2014 Author Premium Share Posted February 24, 2014 So i have a question. How can i approach this task. I want to reject all conections wich are for more than 3 seconds synchronizing? Or these connections which are lagging for more than 15sec? I don't think that's even possible. 1 Link to comment Share on other sites More sharing options...
Yiv 321 Posted March 2, 2014 Share Posted March 2, 2014 At line 4 you write: ext_if="eth0" If I do "ifconfig", there's nothing with eth0 so I have to change? Regards Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted March 2, 2014 Author Premium Share Posted March 2, 2014 (edited) You have to change to whatever the name of the public interface is: For example here my public interface is called re0 Edited August 20, 2022 by Metin2 Dev Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
Mr.Xhater 1 Posted March 5, 2014 Share Posted March 5, 2014 How block 15000 in my pf Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted March 6, 2014 Author Premium Share Posted March 6, 2014 Only the specified ports are open, the rest is blocked. Link to comment Share on other sites More sharing options...
Mr.Xhater 1 Posted March 6, 2014 Share Posted March 6, 2014 Where and what do I have to book now in the PF register so that the port 15000 is blocked and only localhost can access it security fix? Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted March 6, 2014 Author Premium Share Posted March 6, 2014 Can you show me your pf.conf? Link to comment Share on other sites More sharing options...
Kutsuya 0 Posted March 6, 2014 Share Posted March 6, 2014 (edited) You have to change to whatever the name of the public interface is: For example here my public interface is called re0 Juan, You are showing your servers ip address. Edited August 15, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted March 6, 2014 Author Premium Share Posted March 6, 2014 And what's the point in attacking a test server... 1 Link to comment Share on other sites More sharing options...
MORTE 78 Posted November 30, 2014 Share Posted November 30, 2014 how to find out the IP of who is attacking? Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted January 7, 2015 Author Premium Share Posted January 7, 2015 A new sample config for a FreeBSD server running nginx with cloudflare and teamspeak. If you want to use the bruteforce protection feature, install the sshguard-pf package (/usr/ports/security/sshguard-pf) ext_if="igb0" service_ports="{ 22,80,443,10011,30033 }" udp_ports="{ 9987 }" table <trusted_hosts> persist file "/var/db/trusted_hosts" table <abusive_hosts> persist table <sshguard> persist icmp_types = "{ echoreq, unreach }" set block-policy drop set loginterface $ext_if set optimization aggressive set limit { frags 32000, states 64000 } set skip on lo scrub on $ext_if all random-id min-ttl 64 max-mss 1440 set-tos reliability reassemble tcp fragment reassemble antispoof quick for { lo0 $ext_if } block in block in quick on $ext_if proto tcp from <sshguard> to any port 22 label "ssh bruteforce" pass out all keep state pass out on $ext_if all modulate state pass in quick from <trusted_hosts> block in quick from <abusive_hosts> pass inet proto icmp all icmp-type $icmp_types keep state pass in on $ext_if proto tcp to any port $service_ports flags S/SA synproxy state (max-src-conn 50, max-src-conn-rate 25/5, overload <abusive_hosts> flush global) pass in on $ext_if proto udp to any port $udp_ports keep state (max-src-states 5, max-src-conn-rate 5/5, overload <abusive_hosts> flush) In /var/db/trusted_hosts, Cloudflare: 199.27.128.0/21 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/12 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2 Link to comment Share on other sites More sharing options...
Reboot 772 Posted January 7, 2015 Share Posted January 7, 2015 A new sample config for a FreeBSD server running nginx with cloudflare and teamspeak. If you want to use the bruteforce protection feature, install the sshguard-pf package (/usr/ports/security/sshguard-pf) ext_if="igb0" service_ports="{ 22,80,443,10011,30033 }" udp_ports="{ 9987 }" table <trusted_hosts> persist file "/var/db/trusted_hosts" table <abusive_hosts> persist table <sshguard> persist icmp_types = "{ echoreq, unreach }" set block-policy drop set loginterface $ext_if set optimization aggressive set limit { frags 32000, states 64000 } set skip on lo scrub on $ext_if all random-id min-ttl 64 max-mss 1440 set-tos reliability reassemble tcp fragment reassemble antispoof quick for { lo0 $ext_if } block in block in quick on $ext_if proto tcp from <sshguard> to any port 22 label "ssh bruteforce" pass out all keep state pass out on $ext_if all modulate state pass in quick from <trusted_hosts> block in quick from <abusive_hosts> pass inet proto icmp all icmp-type $icmp_types keep state pass in on $ext_if proto tcp to any port $service_ports flags S/SA synproxy state (max-src-conn 50, max-src-conn-rate 25/5, overload <abusive_hosts> flush global) pass in on $ext_if proto udp to any port $udp_ports keep state (max-src-states 5, max-src-conn-rate 5/5, overload <abusive_hosts> flush) In /var/db/trusted_hosts, Cloudflare: 199.27.128.0/21 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/12 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 Thanks fot this 1 Link to comment Share on other sites More sharing options...
Premium Shogun 4585 Posted January 8, 2015 Author Premium Share Posted January 8, 2015 You are welcome let me know if you have any question. The configuration is made by MartPwnS and me based on the original one by Tim which you can find in the first post. Link to comment Share on other sites More sharing options...
cBaraN 109 Posted January 8, 2015 Share Posted January 8, 2015 Thanks @Shogun ... Link to comment Share on other sites More sharing options...
DeYaN. 29 Posted February 9, 2015 Share Posted February 9, 2015 For me,don`t work I copy and paste your config and : No ALTQ support in kernel ALTQ related functions disabled /etc/pf.conf:41: syntax error pfctl: Syntax error in config file: pf rules not loaded The problems is at : Rate limits, trial and error pass in on $ext_if proto tcp to any port $service_ports flags S/SA keep state (max-src-conn 30, max-src-conn-rate 15/5, overload flush) pass in on $ext_if proto {tcp,udp} to any port $game_ports flags S/SA keep state (max-src-conn 30, max-src-conn-rate 15/5, overload flush) Link to comment Share on other sites More sharing options...
Tim 20 Posted March 6, 2015 Share Posted March 6, 2015 The original config (and the modified one too!) uses states to keep track of open connections. The state table however, is by default limited to 10000 entries (FreeBSD 10.1 amd64), which could lead to problems during medium-/large-scale attacks, since new connections will be dropped once the table is full. I usually use the following memory pool limits for PF: set limit { states 100000, frags 20000, src-nodes 100000, table-entries 200000 } Raising the table-entries limit is also a good idea if you have dynamically filled tables of "bad hosts", same goes for src-nodes. It's also recommended to have a few whitelisted static IPs, whose traffic is passed unconditionally and stateless. e.g.: table <ovh> const { 213.186.33.13, 213.186.50.100 } pass in quick on $ext_if from <ovh> to any no state 4 Link to comment Share on other sites More sharing options...
monarchis2 13 Posted December 28, 2017 Share Posted December 28, 2017 Im getting kicked out after char slection. Link to comment Share on other sites More sharing options...
Recommended Posts