如何在FreeBSD上设置PF防火墙来保护Web服务器

时间:2020-01-09 10:39:43  来源:igfitidea点击:

如何在FreeBSD服务器上设置带有PF的防火墙,以使用单个公共IP地址和接口保护Web服务器?

PF是数据包过滤器的首字母缩写。
它是为OpenBSD创建的,但已移植到FreeBSD和其他操作系统。
这是一个有状态的数据包过滤引擎。
本教程将向您展示如何在FreeBSD 10.x和11.x服务器上使用PF设置防火墙来保护您的Web服务器。

步骤1开启PF防火墙

您需要在/etc/rc.conf文件中添加以下三行:

# echo 'pf_enable="YES"' >> /etc/rc.conf
# echo 'pf_rules="/usr/local/etc/pf.conf"' >> /etc/rc.conf
# echo 'pflog_enable="YES"' >> /etc/rc.conf
# echo 'pflog_logfile="/var/log/pflog"' >> /etc/rc.conf

其中:

  • pf_enable =" YES"开启PF服务。
  • pf_rules ="/usr/local/etc/pf.conf"从该文件读取PF规则。
  • pflog_enable =" YES"为PF启用日志记录支持。
  • pflog_logfile ="/var/log/pflog"pflogd应该其中存储日志文件的文件,即,将日志存储在/var/log/pflog文件中。

步骤2在/usr/local/etc/pf.conf中创建防火墙规则

执行以下命令:

# vi /usr/local/etc/pf.conf

追加以下PF规则集:

# vim: set ft=pf
# /usr/local/etc/pf.conf
 
## Set your public interface ##
ext_if="vtnet0"
 
## Set your server public IP address ##
ext_if_ip="172.xxx.yyy.zzz"
 
## Set and drop these IP ranges on public interface ##
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 }"
 
## Set http(80)/https (443) port here ##
webports = "{http, https}"
 
## enable these services ##
int_tcp_services = "{domain, ntp, smtp, www, https, ftp, ssh}"
int_udp_services = "{domain, ntp}"
 
## Skip loop back interface - Skip all PF processing on interface ##
set skip on lo
 
## Sets the interface for which PF should gather statistics such as bytes in/out and packets passed/blocked ##
set loginterface $ext_if
 
## Set default policy ##
block return in log all
block out all
 
# Deal with attacks based on incorrect handling of packet fragments 
scrub in all
 
# 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
 
## Blocking spoofed packets
antispoof quick for $ext_if
 
# Open SSH port which is listening on port 22 from VPN 139.xx.yy.zz Ip only
# I do not allow or accept ssh traffic from ALL for security reasons 
pass in quick on $ext_if inet proto tcp from 139.xxx.yyy.zzz to $ext_if_ip port = ssh flags S/SA keep state label "USER_RULE: Allow SSH from 139.xxx.yyy.zzz"
## Use the following rule to enable ssh for ALL users from any IP address #
## pass in inet proto tcp to $ext_if port ssh
### [ OR ] ###
## pass in inet proto tcp to $ext_if port 22 
 
# Allow Ping-Pong stuff. Be a good sysadmin 
pass inet proto icmp icmp-type echoreq
 
# All access to our Nginx/Apache/Lighttpd Webserver ports 
pass proto tcp from any to $ext_if port $webports
 
# Allow essential outgoing traffic 
pass out quick on $ext_if proto tcp to any port $int_tcp_services
pass out quick on $ext_if proto udp to any port $int_udp_services
 
# Add custom rules below

保存并关闭文件。

要检查语法错误,请运行:

# service pf check

或者

/etc/rc.d/pf check

或者

# pfctl -n -f /usr/local/etc/pf.conf

步骤3启动PF防火墙

请注意,您可能会通过基于ssh的会话从服务器断开连接:

启动PF

# service pf start

停止PF

# service pf stop

检查PF是否存在语法错误

# service pf check

重新启动PF

# service pf restart

查看PF状态

# service pf status

输出示例:

Status: Enabled for 0 days 00:02:18           Debug: Urgent
 
Interface Stats for vtnet0            IPv4             IPv6
  Bytes In                           19463                0
  Bytes Out                          18541                0
  Packets In
    Passed                             244                0
    Blocked                              3                0
  Packets Out
    Passed                             136                0
    Blocked                             12                0
 
State Table                          Total             Rate
  current entries                        1               
  searches                             395            2.9/s
  inserts                                4            0.0/s
  removals                               3            0.0/s
Counters
  match                                 19            0.1/s
  bad-offset                             0            0.0/s
  fragment                               0            0.0/s
  short                                  0            0.0/s
  normalize                              0            0.0/s
  memory                                 0            0.0/s
  bad-timestamp                          0            0.0/s
  congestion                             0            0.0/s
  ip-option                              0            0.0/s
  proto-cksum                            0            0.0/s
  state-mismatch                         0            0.0/s
  state-insert                           0            0.0/s
  state-limit                            0            0.0/s
  src-limit                              0            0.0/s
  synproxy                               0            0.0/s
  map-failed                             0            0.0/s

启动/停止/重新启动pflog服务的命令

执行以下命令:

# service pflog start
# service pflog stop
# service pflog restart

步骤4 pfctl命令快速入门

您需要使用pfctl命令查看PF规则集和参数配置,包括来自数据包过滤器的状态信息。
让我们查看所有常见命令:

显示PF规则信息

# pfctl -s rules

输出示例:

block return in log all
block drop out all
block drop in quick on ! vtnet0 inet from 172.xxx.yyy.zzz/24 to any
block drop in quick inet from 172.xxx.yyy.zzz/24 to any
pass in quick on vtnet0 inet proto tcp from 139.aaa.ccc.ddd to 172.xxx.yyy.zzz/24 port = ssh flags S/SA keep state label "USER_RULE: Allow SSH from 139.aaa.ccc.ddd"
pass inet proto icmp all icmp-type echoreq keep state
pass out quick on vtnet0 proto tcp from any to any port = domain flags S/SA keep state
pass out quick on vtnet0 proto tcp from any to any port = ntp flags S/SA keep state
pass out quick on vtnet0 proto tcp from any to any port = smtp flags S/SA keep state
pass out quick on vtnet0 proto tcp from any to any port = http flags S/SA keep state
pass out quick on vtnet0 proto tcp from any to any port = https flags S/SA keep state
pass out quick on vtnet0 proto tcp from any to any port = ftp flags S/SA keep state
pass out quick on vtnet0 proto tcp from any to any port = ssh flags S/SA keep state
pass out quick on vtnet0 proto udp from any to any port = domain keep state
pass out quick on vtnet0 proto udp from any to any port = ntp keep state

显示每个规则的详细输出

# pfctl -v -s rules

为每个规则添加带有详细输出的规则编号

# pfctl -vvsr show

显示状态

# pfctl -s state
# pfctl -s state | more
# pfctl -s state | grep 'something'

如何从CLI禁用PF

# pfctl -d

如何从CLI启用PF

# pfctl -e

如何从CLI刷新所有PF规则/nat /表

# pfctl -F all

输出示例:

rules cleared
nat cleared
0 tables deleted.
2 states cleared
source tracking entries cleared
pf: statistics cleared
pf: interface flags reset

如何仅从CLI刷新PF规则

# pfctl -F rules

如何仅从CLI刷新队列

# pfctl -F queue

如何从CLI刷新不属于任何规则的所有统计信息

# pfctl -F info

如何从CLI清除所有计数器

# pfctl -z clear

步骤5请参阅PF日志

PF日志为二进制格式。
要查看它们,请执行:

# tcpdump -n -e -ttt -r /var/log/pflog

要查看实时日志运行:

# tcpdump -n -e -ttt -i pflog0