Answers:
#!/bin/bash
WHITELIST=/whitelist.txt
BLACKLIST=/blacklist.txt
#THIS WILL CLEAR ALL EXISTING RULES!
echo 'Clearing all rules'
iptables -F
#
## Whitelist
#
for x in `grep -v ^# $WHITELIST | awk '{print $1}'`; do
echo "Permitting $x..."
$IPTABLES -A INPUT -t filter -s $x -j ACCEPT
done
#
## Blacklist
#
for x in `grep -v ^# $BLACKLIST | awk '{print $1}'`; do
echo "Denying $x..."
$IPTABLES -A INPUT -t filter -s $x -j DROP
done
#!/bin/bash
ALLOWEDTCP="80 3128 3784"
ALLOWEDUDP="3128 3784"
#
## Permitted Ports
#
for port in $ALLOWEDTCP; do
echo "Accepting port TCP $port..."
$IPTABLES -A INPUT -t filter -p tcp --dport $port -j ACCEPT
done
for port in $ALLOWEDUDP; do
echo "Accepting port UDP $port..."
$IPTABLES -A INPUT -t filter -p udp --dport $port -j ACCEPT
done
# Attempt to block portscans
# Anyone who tried to portscan us is locked out for an entire day.
iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP
# Once the day has passed, remove them from the portscan list
iptables -A INPUT -m recent --name portscan --remove
iptables -A FORWARD -m recent --name portscan --remove
# These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
# Reject spoofed packets
# These adresses are mostly used for LAN's, so if these would come to a WAN-only server, drop them.
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
#Multicast-adresses.
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
# Drop all invalid packets
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP
# Stop smurf attacks
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -j DROP
# Drop excessive RST packets to avoid smurf attacks
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
# Don't allow pings through
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
iptables
在第8行上,然后再行$IPTABLES
。仅在iptables
任何地方使用就足够了吗?否则我想您需要分配类似IPTABLES=/sbin/iptables
权利的东西?
ipset
如果您仅基于IP,端口或同时基于这两者编写了许多类似的规则,请考虑使用ipset
来优化netfilter的性能。
例如:
iptables -s 192.168.1.11 -j ACCEPT
iptables -s 192.168.1.27 -j ACCEPT
iptables -s 192.168.1.44 -j ACCEPT
... hundreds of similar rules ...
iptables -s 192.168.251.177 -j ACCEPT
这意味着源地址为192.168.251.177的数据包必须先遍历数百条规则,然后才能得出接受ACCEPT的结论。
当然,经验丰富的系统管理员会按子网划分规则。但这仍然意味着数百条规则。
ipset
营救!
首先,定义一个IP集ipmap
类型:
ipset -N Allowed_Hosts ipmap --network 192.168.0.0/16
然后,用地址填充它:
for ip in $LIST_OF_ALLOWED_IP; do ipset -A Allowed_Hosts $ip; done
最后,用一个规则替换上面的数百个iptables规则:
iptables -m set --match-set Allowed_Hosts src -j ACCEPT
当数据包到达时,netfilter将根据IP集对数据包的源(src)IP 执行非常快速的位图搜索Allowed_Hosts
。来自192.168.0.0/16的所有数据包都将遵循一条规则。并且一定要相信我,搜索位图至少比执行数百个iptables规则检查快两个数量级。
ipset
不限于IP地址。它还可以根据端口,IP端口元组,网络/子网地址,IP-MAC元组等进行匹配。它可以将这些条件匹配为源或目标,或两者的混合(在元组的情况下)。
最后,ipset
您可以自动将IP地址放入黑名单/白名单。这些黑名单/白名单也可以“老化”,从而在经过可配置的时间后自动删除IP地址。
有关更多详细信息,请参见ipset
的手册页。
某些Linux发行版可能不提供“现成的”支持ipset
(例如,Ubuntu 10.04出现了此问题)。在这些系统上,一种方法是ipset
从源代码安装。
而是ipset
从其网站下载的源:http : //ipset.netfilter.org/install.html
另外,如果你使用xtables-addons
,IPSET 被包含在它的源:http://xtables-addons.sourceforge.net/
添加以下规则,最好在 -t raw -A PREROUTING
-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
被阻止的攻击分别是:
(可以随意编辑以上攻击的名称)
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
可以被删除,因为-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
会抓住每一个包时,它可以阻止。
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
步骤1设置内核参数以允许ip转发,步骤2设置iptables规则,该规则在接口eth0上启用NAT。
/etc/sysctl.conf
net.ipv4.ip_forward = 1
。(假设使用Red Hat或衍生产品。)
添加以下规则,最好在 -t raw -A PREROUTING
-p icmp -m u32 ! --u32 "4&0x3FFF=0" -j DROP
-p icmp -m length --length 1492:65535 -j DROP
第一条规则阻止“碎片标记”不为0的所有ICMP数据包。(ICMP 永远不应分段;它们应携带小的有效载荷)
第二条规则阻止过大的未分段的ICMP数据包。
(从我的iptables_tricks.txt文件中,从很多地方重新编译过:P)
使iptables在端口22(SSH)上来自同一IP的新连接之间等待15秒:
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 5 --rttl --name SSH -j DROP
IPTABLES视频教程
第1集 http://www.youtube.com/watch?v=ldB8kDEtTZA&feature=player_embedded
第2集 http://www.youtube.com/watch?v=aDaEXxRHeXY&feature=related
最后一集
http://www.youtube.com/watch?v=JojqHKcSxpo&feature=player_embedded
对于任何新手来说都是一个好的开始。
已经有一个提到IP集的答案。但是,它是一维的,因为它着重于经典规则的性能提升以及IP设置缓解了人们拥有的大量IP地址无法用CIDR表示法轻易地表示为子网的问题。
因为ipset
我将使用读取ipset restore
和写入的符号ipset save
。
对应于iptables
(和ip6tables
)规则,我将使用读取iptables-restore
和写入的表示法iptables-save
。这样可以简化符号,并让我突出显示潜在的仅IPv4(带前缀-4
)或仅IPv6(带前缀-6
)规则。
在某些示例中,我们会将数据包流转移到另一个链中。假定该链存在于该点,因此不会生成用于创建链的行(也未提及表名或COMMIT
末尾的命令-ted)。
IP集可以做的比其他答案中提到的要多得多,除了这里的简短条目之外,您还应该阅读IP集文档(ipset(8)
)iptables-extensions(8)
。
例如,我会主要集中在三个集类型:hash:ip
,hash:net
和list:set
,但更多的是比它们都具有有效的用例。
例如,您还可以匹配端口号,而不仅仅是IP地址。
iptables-save
和保存和还原IP集iptables-restore
您可以批量创建IP集声明,并将它们通过管道导入到中ipset restore
。如果要使命令对已有的条目更具弹性,请使用ipset -exist restore
。
如果您的规则位于一个名为的文件中,则default.set
可以使用:
ipset -exist restore < default.set
这样的文件可以包含要create
设置的add
条目和其中的条目。但是通常大多数命令行命令似乎在文件中都有相应的版本。示例(创建一组DNS服务器):
create dns4 hash:ip family inet
create dns6 hash:ip family inet6
# Google DNS servers
add dns4 8.8.8.8
add dns4 8.8.4.4
add dns6 2001:4860:4860::8888
add dns6 2001:4860:4860::8844
这里为IPv4(dns4
)创建了一组,为IPv6(dns6
)创建了一组。
IP集合中的超时可以设置为每个集合以及每个条目的默认值。这在您要临时阻止某人的情况下非常有用(例如,用于端口扫描或尝试强行使用SSH服务器)。
其工作方式如下(创建IP集期间的默认设置):
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
我们将在下面返回这些特定的集合,以及为什么要按原样设置它们的理由。
如果您想为特定的IP地址设置超时时间,则可以简单地说:
add ssh_dynblock4 1.2.3.4 timeout 7200
将IP 1.2.3.4阻止两个小时,而不是(设置的)默认半小时。
如果ipset save ssh_dynblock4
过一会儿再看,您会发现类似以下内容:
create ssh_dynblock4 hash:ip family inet hashsize 1024 maxelem 65536 timeout 1800
add ssh_dynblock4 1.2.3.4 timeout 6954
Kernel error received: Unknown error -1
)。sudo ipset add ssh_dynblock4 1.2.3.4 timeout $((120*60))
在脚本内部,查看条目是否已存在可能很有用。可以实现ipset test
这一点,如果该条目存在,则返回零,否则返回非零。因此,通常的检查可以在脚本中应用:
if ipset test dns4 8.8.8.8; then
echo "Google DNS is in the set"
fi
但是,在许多情况下,您宁愿使用-exist
switch ipset
来指示它不要抱怨现有条目。
iptables
规则中填充IP集我认为,这是IP集的杀手级功能之一。您不仅可以与IP集的条目进行匹配,还可以将新条目添加到现有IP集。
例如,在此问题的答案中,您有:
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
...旨在限制对SSH(TCP端口22)的连接尝试的速率。使用的模块recent
跟踪最近的连接尝试。但是state
,我更喜欢conntrack
模块而不是模块。
# Say on your input chain of the filter table you have
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
# Then inside the SSH chain you can
# 1. create an entry in the recent list on new connections
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
# 2. check whether 3 connection attempts were made within 2 minutes
# and if so add or update an entry in the ssh_dynblock4 IP set
-4 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock4 src --exist
-6 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock6 src --exist
# 3. last but not least reject the packets if the source IP is in our
# IP set
-4 -A SSH -m set --match-set ssh_dynblock4 src -j REJECT
-6 -A SSH -m set --match-set ssh_dynblock6 src -j REJECT
在这种情况下,我会将流程重定向到SSH
链,这样我就不必-p tcp --dport ssh
为每个规则重复自己。
重申:
-m set
让iptables
知道,我们用的开关从set
模块(负责处理IP套)--match-set ssh_dynblock4 src
告诉iptables
将源(src
)地址与命名集(ssh_dynblock4
)
相匹配sudo ipset test ssh_dynblock4 $IP
(其中$IP
包含数据包的源IP地址)-j SET --add-set ssh_dynblock4 src --exist
从数据包中添加或更新源(src
)地址到IP集中ssh_dynblock4
。如果存在一个条目(--exist
),它将被简单地更新。
sudo ipset -exist add ssh_dynblock4 $IP
(其中$IP
包含数据包的源IP地址)如果您想匹配目标/目标地址,请使用dst
代替src
。有关更多选项,请查阅手册。
IP集可以包含其他集。现在,如果您一直关注本文,您会想知道是否可以组合集合。当然是。对于上面的IP集,我们可以创建两个联合集ssh_dynblock
,ssh_loggedon
分别包含仅IPv4和仅IPv6集:
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
# Sets of sets
create ssh_loggedon list:set
create ssh_dynblock list:set
# Populate the sets of sets
add ssh_loggedon ssh_loggedon4
add ssh_loggedon ssh_loggedon6
add ssh_dynblock ssh_dynblock4
add ssh_dynblock ssh_dynblock6
接下来要想到的问题是,这是否允许我们以与 IP版本无关的方式匹配和操作IP集。
答案是肯定的:是的!(ala,我上次检查时没有明确记录)
因此,上一节中的规则可以重写为:
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
这更加简洁。是的,这是经过尝试和测试的,它就像一种魅力。
在我的服务器上,我有一个脚本作为cron
作业运行,该脚本需要一堆主机名并将其解析为IP地址,然后将其输入到“可信主机”的IP集中。这个想法是,受信任的主机会尝试更多登录到服务器,并且不必像其他任何人一样被阻止出去。
相反,除了受信任主机的(潜在)例外(即规则顺序很重要)之外,我阻止了整个国家/地区连接到我的SSH服务器。
但是,这留给读者练习。在这里,我想添加一个整洁的解决方案,该解决方案将使用集合中包含的ssh_loggedon
集合来允许进行后续的连接尝试,而不会受到与其他数据包相同的审查。
请注意以下规则,记住默认的超时时间为90分钟ssh_loggedon
和30分钟,这一点很重要:ssh_dynblock
iptables
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m set --match-set ssh_loggedon src -j ACCEPT
-A SSH -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
现在,您应该问自己,连接IP地址在ssh_loggedon
子集中是如何结束的。所以请继续阅读...
如果您尝试了sshrc
和朋友,您将了解到它的缺点。但是PAM可以提供帮助。名为模块的模块pam_exec.so
使我们可以在SSH登录期间调用一个脚本,该操作使我们知道该用户已被允许进入。
在和条目/etc/pam.d/sshd
下方pam_env
,pam_selinux
添加以下行:
session optional pam_exec.so stdout /path/to/your/script
并确保您的脚本版本(/path/to/your/script
上面)存在并且可以执行。
PAM使用环境变量来传达正在发生的事情,因此您可以使用这样的简单脚本:
#!/bin/bash
# When called via pam_exec.so ...
SETNAME=ssh_loggedon
if [[ "$PAM_TYPE" == "open_session" ]] && [[ -n "$PAM_RHOST" ]]; then
[[ "x$PAM_RHOST" != "x${PAM_RHOST//:/}" ]] && SETNAME="${SETNAME}6" || SETNAME="${SETNAME}4"
ipset -exist add $SETNAME "$PAM_RHOST"
fi
不幸的是,该ipset
实用程序似乎没有内置的netfilter智能。因此,在添加条目时,我们需要区分IPv4和IPv6 IP集。否则ipset
将假定我们要向该组集合中添加另一组而不是IP。当然,不太可能会有一个以IP命名的集合:)
因此,在这种情况下(否则),我们将检查:
IP地址并追加6
到设置名称中4
。
结束。
可以用来配置iptables的另一个GUI是Firewall Builder。它使用户可以将规则元素创建为数据库中的对象,然后将这些对象拖放到规则编辑器中以创建所需的防火墙策略。然后,应用程序将生成一个脚本文件,其中包含实施规则所需的所有iptables命令。
与某些其他iptables GUI解决方案不同,后者只能一次管理一个iptables配置,而使用Firewall Builder,您可以从单个应用程序管理大量的iptables配置。Firewall Builder在Linux,Windows和Mac OS X上运行,已经存在了10多年,并且在全球拥有成千上万的活跃用户。
全面披露-我是NetCitadel的联合创始人,NetCitadel是开发Firewall Builder的公司。
使用uid记录传出连接
iptables -A OUTPUT -m state --state NEW -m tcp -p tcp -m limit --limit 5/m -j LOG --log-uid --log-prefix="outgoing connection: "
端口/连接转发:
iptables -A PREROUTING -t nat -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.1.7:80
iptables -A INPUT -p tcp -m state --state NEW --dport 80 -i eth1 -j ACCEPT
NFLOG
目标。它允许使用更长的行前缀,并且用户模式守护程序也可以登录数据库。
示例:您有eth0
和 eth1
想要允许它们之间的任何流量?
iptables -A FORWARD -i eth+ -o eth+ -j ACCEPT
我过去曾使用过此命令,以匹配veth<something>
由LXC动态创建和命名的接口。因此,我可以一次将所有匹配veth+
。
我还特意命名了一些接口_<something>
以与匹配_+
。
iptables -t mangle -A PREROUTING -p tcp \
-m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
此目标的目的是检查发送SYN数据包的主机是否建立了连接,或者在启动SYN连接之后不执行任何操作。如果不执行任何操作,它将以最小的努力丢弃该数据包。
将syn数据包设置到原始表中的连接跟踪表
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 --syn -j CT --notrack
为http服务器启用synproxy:
iptables -A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate INVALID,UNTRACKED \
-j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
使用IP集将所有单个IP地址限制为出站带宽配额
您可能需要将服务器配置为每个月仅允许每个IP 15GiByte的带宽使用,以反映或躲避带宽使用攻击,也许是针对ISP的计量带宽配额。可以通过以下方式实现:
首先为IPv4和IPv6创建IP集:
ipset create IP_QUOTA_SET_OUT hash:ip timeout 345600 counters
ipset create IP_QUOTA_SET_OUT_INET6 hash:ip timeout 345600 counters family inet6
现在添加您的iptables规则。如果尚不存在,则第一行会将IP添加到集合中。如果为该组IP传输的字节数大于指定的数量,则第二行将不匹配。然后对IPv6进行相同的操作。
iptables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT dst -j SET --add-set IP_QUOTA_SET_OUT dst --timeout 345600
iptables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT dst --bytes-gt 16106127360 -j DROP
ip6tables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT_INET6 src -j SET --add-set IP_QUOTA_SET_OUT_INET6 src --timeout 345600
ip6tables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT_INET6 src --bytes-gt 16106127360 -j DROP
这将防止攻击,例如用户长时间从您的Web服务器请求大文件,或与此相关的任何服务。对于INPUT链也可以这样做。
我所做的主要是因为我对更精致的解决方案不了解,所以每4小时手动检查一次我的Nginx日志,每2分钟检查一次邮件服务器的日志,以检查单个IP的访问量是否过多。我一起运行了一些脚本:
access.log
并列出按服务器点击次数排序的前10个IPiptables.save
看起来是这样的:
autoBanIPs_mail.sh#!/bin/bash
# This script checks the last 2 minutes of log entries to see if any
# IP has made over 99 connections
now=$(date +"%m_%d_%Y")
/root/bin/checkBadIPs_mail.sh > /home/ipChecker/ipcheckMAIL_$now.txt
cat /home/ipChecker/ipcheckMAIL_$now.txt | \
grep " \\(\\([9][9]\\)\\|\\([0-9][0-9][0-9]\\+\\)\\) " | \
awk '{print $2}' > /home/ipChecker/badMailIPs_$now.sh
sed -i "s/^/\/usr\/local\/sbin\/blockIP /g" /home/ipChecker/badMailIPs_$now.sh
/bin/bash /home/ipChecker/badMailIPs_$now.sh
cat /home/ipChecker/ipcheckMAIL_$now.txt >> /home/ipChecker/ipcheckMAIL_$now.log
rm /home/ipChecker/ipcheckMAIL_$now.txt
rm /home/ipChecker/badMailIPs_$now.sh
checkBadIPs_mail.sh
这里要特别注意的一件事是,您需要设置白名单,否则您将开始阻止来自服务器的大量真实IP,而这些服务器只是从中收到大量电子邮件,或者在其他日志的情况下,IP是出于正当原因,对您的服务器造成了很大的影响。我的白名单只是通过在|之后添加grep管道而内置到此脚本中的 grep']' | 看起来像这样的“ grep -v 127.0 |” 。
您需要花时间教您的服务器哪些高流量IP是合法的,哪些不是。对我而言,这意味着我必须花大约第一周的时间每隔几个小时手动检查一次我的日志,在iplocation.net上查找流量较高的ip,然后添加诸如Amazon,box.com甚至我的家庭/办公室之类的合法文件IP属于此白名单。如果不这样做,则很可能会阻止您使用自己的服务器,或者您将开始阻止合法的邮件/ Web服务器,并导致电子邮件或流量中断。
cat /var/log/mail.log | awk \
-v d1="$(date --date="-2 min" "+%b %_d %H:%M")" \
-v d2="$(date "+%b %_d %H:%M")" \
'$0 > d1 && $0 < d2 || $0 ~ d2' | \
grep '\[' | grep '\]' | \
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -v 127.0 | \
awk '{print $1}' | sort | uniq -c | sort -n | tail -10
块IP
#!/bin/bash
sudo iptables -I INPUT -s $1 -j DROP
sudo bash -c "iptables-save > /etc/network/iptables.save"
再一次,我知道这简直是地狱,可能有一个很好的干净有效的协议可以完成所有这些工作,但我对此一无所知,这件事已经进行了一年或两年,并阻止了坏人。我非常推荐的一件事是,您可以使用代理或其他服务器来访问主服务器。原因是,如果您一天都在进行Web开发,那在5个小时内对您的自我执行ping操作2000次,以进行某些测试,除了代理服务器,您可能无法进入,就被封锁了。
您可以看到,在checkBadIPs.sh
我放置grep -v 127.0的过程中,在我的实际文件中,我对自己的IP和其他受信任的IP范围有很多忽略规则,但是有时您的IP更改了,您忘记了更新,然后就被锁定了在您自己的服务器之外。
无论如何,希望能有所帮助。
我做了一些更改,因此现在不用每隔几个小时检查一次,而是每2分钟检查一次一些日志,主要是ssh auth日志和邮件日志,因为它们受到了很大的打击:(。
我为每个日志文件设置了特定的脚本,尽管从想要检查日志时使用的手动脚本可以很容易地做到这一点。看起来像这样:
#!/bin/bash
log=$1 time=$2
cat /var/log/${log} | awk \
-v d1="$(date --date="-${time} min" "+%b %_d %H:%M")" \
-v d2="$(date "+%b %_d %H:%M")" \
'$0 > d1 && $0 < d2 || $0 ~ d2' | \
grep '\[' | grep '\]' | \
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \
sort | uniq -c | sort -n | tail -10
在运行时,这需要2个输入,要扫描的日志文件以及要扫描的历史距离。
因此,如果我想检查mail.log以获取IP计数,比如说过去75分钟,我将运行:
$ sudo script.sh mail.log 75
ipset
而不是延长iptables链,但是这个主意很棒,我想我会将它们应用于我的生产服务器。感谢分享!
我同意有关ipsets和tcp标志的评论,但是仍然缺少很多内容:
将xtables-addons geoip匹配而不是ipset用于国家/地区列表。定期更新geoip数据(每月至少一次)。数据比即发即弃的ipset列表更加动态。
考虑使用tcp标志进行连接状态跟踪。例如,tcp RST或ACK仅对已建立的连接有意义。SYN仅对新的和相关的连接有意义。对于已建立的连接,SYN意味着您的SYN + ACK丢失或黑客尝试,应重置,因为连接的双方均不同意声明。
尽管SYN + RST和FIN + RST都不是非法组合,但是SYN + FIN现在在TCP快速打开(TCP选项34)下有效,尤其是对于DNS。即使具有快速打开的SYN数据包也不应分段。我不认为带有PSH和URG标志的规则有用。不要将连接跟踪状态与TCP状态混淆:建立对SYN数据包的RST响应是为了进行跟踪。
SYNPROXY用于转发数据包,对于超出syncookie支持范围的本地传送数据包不添加任何内容。
ICMP错误数据包将始终处于相关状态,并且长度为48:576(如果有效)。IPv6的长度为84:1280。所有其他都应该忽略。由于它们的最大大小也是最小MTU,因此永远不要将它们分割成碎片。ICMP请求(ping,时间戳等)将始终是新的,并且已建立回复。在其他状态下丢弃ICMP数据包。
像带有最新列表且仅接受后续SYN数据包的SSH示例一样,对SMTP也应这样做,这与仅在IP地址数据上进行“灰名单”相似。
在过滤器表中,输入和输出链中的第一个(或第二个,如果先接受已建立的状态数据包)规则应接受回送接口上的所有内容。您应该信任自己的内部数据包。如果不能,那么您将面临防火墙解决方案之外的更大问题。
最后,除非您真的了解规则,否则不要盲目复制规则。如此多的类似规则列表可以做到这一点,并且在大多数情况下,结果是可笑的。
#!/bin/bash
# The following iptables/ip6tables configurations have
# been kindly shared with us from ArckWiki. There are
# a few additions apart from what has been defined.
#
#=================Flush current definitions==============
iptables -F
ip6tables -F
iptables -X
ip6tables -X
#
#=================Chains=================================
#
#----Define chains for opened ports
iptables -N TCP
ip6tables -N TCP
iptables -N UDP
ip6tables -N UDP
#
#----Setting up the filter table for NAT
# iptables -N fw-interfaces
# ip6tables -N fw-interfaces
# iptables -N fw-open
# ip6tables -N fw-open
#
#================Default Chain reactions=================
#
#----Default FORWARD reaction
iptables -P FORWARD DROP
ip6tables -P FORWARD DROP
#
#----Default OUTPUT reaction
iptables -P OUTPUT ACCEPT
ip6tables -P OUTPUT ACCEPT
#
#----Shellshock
iptables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
ip6tables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
#
#----Default INPUT reaction
iptables -P INPUT DROP
ip6tables -P INPUT DROP
#
#----Drop spoofing packets
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i wlan0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i wlan1 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
#
#================Ping rate limiting globally=============
iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 30/min --limit-burst 8 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 --match limit --limit-burst 8 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -j DROP
ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 -j DROP
#
#----flooding RST packets, smurf attack Rejection
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
#
#----Bogus packet DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
ip6tables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
ip6tables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
#
#================RELATED,ESTABLISHED reaction============
iptables -A INPUT --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#
#================unfetered loopback======================
iptables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
#
#================INVALID catagory of packets=============
iptables -A INPUT -p 41 -j ACCEPT
iptables -A INPUT --match conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT --match conntrack --ctstate INVALID -j DROP
#
#================IPv6 reactions and definitions==========
ip6tables -A INPUT -s fe80::/10 -p icmpv6 -j ACCEPT
ip6tables -t raw -A PREROUTING -p icmpv6 -s fe80::/10 -j ACCEPT
ip6tables -t raw -A PREROUTING --match rpfilter -j ACCEPT
ip6tables -t raw -A PREROUTING -j DROP
#
#=======Acceptable INVALIDs and a curteous response======
iptables -A INPUT -p udp --match conntrack --ctstate NEW -j UDP
ip6tables -A INPUT -p udp --match conntrack --ctstate NEW -j UDP
iptables -A INPUT -p tcp --syn --match conntrack --ctstate NEW -j TCP
ip6tables -A INPUT -p tcp --syn --match conntrack --ctstate NEW -j TCP
#
#================Defining the TCP and UDP chains
#
#########################################################
# Notes for port open definitions #
# It is important to note that this should be config- #
# ured differently if you're providing any routing #
# activity for any purpose. it is up to you to actively #
# define what suites your needs to get the job done. #
# In this example, I'm exempting IPv6 from being able #
# to interact with SSH protocols for two reasons. The #
# first is because it is generally easier and more com- #
# for internal networks to be deployed with IPv4. The #
# second reason is, IPv6 can be deployed globally. #
#########################################################
#
#----SSH configured for eth0
iptables -A TCP -i eth0 -p tcp --dport ssh -j ACCEPT
#!---Blocking SSH interactions in IPv6
ip6tables -A TCP -p tcp --dport ssh -j DROP
#!---Leave commented for end service device
# iptables -A TCP -p tcp --dport 80 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 80 -j ACCEPT
# iptables -A TCP -p tcp --dport 443 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 443 -j ACCEPT
#
#!---Uncomment for remote service to this device
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 22 -j ACCEPT
#
#!---Uncomment if you're providing routing services
# iptables -A UDP -p udp 53 -j ACCEPT
# ip6tables -A UDP -p udp 53 -j ACCEPT
#
#=================Tricking port scanners=================
#
#----SYN scans
iptables -I TCP -p tcp --match recent --update --seconds 60 --name TCP-PORTSCAN -j DROP
ip6tables -I TCP -p tcp --match recent --update --seconds 60 --name TCP-PORTSCAN -j DROP
iptables -A INPUT -p tcp --match recent --set --name TCP-PORTSCAN -j DROP
ip6tables -A INPUT -p tcp --match recent --set --name TCP-PORTSCAN -j DROP
#
#----UDP scans
iptables -I UDP -p udp --match recent --update --seconds 60 --name UDP-PORTSCAN -j DROP
ip6tables -I UDP -p udp --match recent --update --seconds 60 --name UDP-PORTSCAN -j DROP
iptables -A INPUT -p udp --match recent --set --name UDP-PORTSCAN -j DROP
ip6tables -A INPUT -p udp --match recent --set --name UDP-PORTSCAN -j DROP
#
#----For SMURF attack protection
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m limit --limit 2/second --limit-burst 2 -j ACCEPT
ip6tables -A INPUT -p icmpv6 -m limit --limit 2/second --limit-burst 2 -j ACCEPT
#
#----Ending all other undefined connections
iptables -A INPUT -j DROP
ip6tables -A INPUT -j DROP
#
#=======Defining the IN_SSH chain for bruteforce of SSH==
#
#!---I've elected to keep IPv6 out of this realm for
#!---ease of use
iptables -N IN_SSH
iptables -A INPUT -p tcp --dport ssh --match conntrack --ctstate NEW -j IN_SSH
iptables -A IN_SSH --match recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j DROP
iptables -A IN_SSH --match recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j DROP
iptables -A IN_SSH --match recent --name sshbf --set -j ACCEPT
iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
#
#==================Setting up a NAT gateway==============
#
#########################################################
# #
# I commented this half out because it's not something #
# that will apply to all setups. Make note of all par- #
# tinate interfaces and what exactly is going on. #
# #
#########################################################
#
#----Setting up the FORWARD chain
# iptables -A FORWARD --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# ip6tables -A FORWARD --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#
#
#----Defining the fw-interfaces/open chains for FORWARD
# iptables -A FORWARD -j fw-interfaces
# ip6tables -A FORWARD -j fw-interfaces
# iptables -A FORWARD -j fw-open
# ip6tables -A FORWARD -j fw-open
# iptables -A FORWARD -j DROP # Should be REJECT. But, fuck them
# ip6tables -A FORWARD -j DROP
# iptables -P FORWARD DROP
# ip6tables -P FORWARD DROP
#
#
#----Setting up the nat table
# iptables -A fw-interfaces -i ### -j ACCEPT
# ip6tables -A fw-interfaces -i ### -j ACCEPT
# iptables -t nat -A POSTROUTING -s w.x.y.z/S -o ppp0 -j MASQUERADE
# ip6tables -t nat -A POSTROUTING -s fe::/10 -o ppp0 -j MASQUERADE
#----The above lines should be repeated specifically for EACH interface
#
#----Setting up the PREROUTING chain
#
#######################################################
# #
# The PREROUTING chain will redirect either port #
# targets to be redirected. This can also redirect #
# traffic inbound to your network from the gateway #
# to this machine. This can be useful if you're using #
# a honeypot or have any service within your network #
# that you want to be pointed to a specific device. #
# #
#######################################################
#
#----SSH honeypot server
# iptables -A fw-open -d HONEYPOT_IP -p tcp --dport 22 -j ACCEPT
# ip6tables -A fw-open -d HONEYPOT_IP -p tcp --dport 22 -j ACCEPT
#----With intuition, you can configure the above to also direct specific
#----requests to other devices providing those services. The bellow will
#----be for a squid server
# iptables -A fw-open -d SQUID_IP -p tcp --dport 80 -j ACCEPT
# ip6tables -A fw-open -d SQUID_IP -p tcp --dport 80 -j ACCEPT
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to SQUID_IP
# ip6tables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to SQUID_IP
#
#===============Declare configurations=================
iptables -nvL
ip6tables -nvL