第一步 - 更新获取最新的软件

对于任何系统来说,最大的安全防御就是将自己的软件更新至最新版本。软件更新会安装新版本的漏洞修复补丁。

自动安全更新

自动更新是你必须自己判断接下来你要做什么。记住自动更新仅用于从软件源安装的包,而不是自己手动编译的软件。你会发现,你需要一个和生产环境保持一致性的测试服务器。所有更新可以先在测试环境试验然后再部署至生产环境。

第二步 - 添加一个限制了权限的普通用户

默认情况,你都是使用没有任何权限控制的Root用户登录服务器,你可以在服务器上运行任何指令,所以,强烈建议使用一个被限制了权限的普通用户。你可以使用 sudo 指令暂时提高自己的用户权限,确保可以暂时执行一些需要管理员权限才能执行的任务。 不是所有的Linux版本都默认有sudo指令,如果你发现使用sudo时出现sudo: command not found提示,那你需要先安装sudo

添加新用户的方法:

CentOS / Fedora

  1. # 添加用户example_user
  2. useradd example_user && passwd example_user
  3. # 添加用户至 wheel 组,确保拥有sudo执行权限。
  4. usermod -aG wheel example_user

在Linux中wheel组就类似于一个管理员的组。通常在LUNIX下,即使我们有系统管理员root的权限,也不推荐用root用户登录。一般情况下用普通用户登录就可以了,在需要root权限执行一些操作时,再su登录成为root用户。但是,任何人只要知道了root的密码,就都可以通过su命令来登录为root用户--这无疑为系统带来了安全隐患。所以,将普通用户加入到wheel组,被加入的这个普通用户就成了管理员组内的用户,但如果不对一些相关的配置文件进行配置,这个管理员组内的用户与普通用户也没什么区别--就像警察下班后,没有带枪、穿这便衣和普通人(用户)一样,虽然他的的确确是警察。

根据应用的实例不同应用wheel组的方法也不同。这里对于服务器来说,我们希望的是剥夺被加入到wheel组用户以外的普通用户通过su命令来登录为root的机会(只有属于wheel组的用户才可以用su登录为root)。这样就进一步增强了系统的安全性。

只有属于wheel组的用户才可以用su登录为root,实现方法: 具体步骤如下:

1)修改 /etc/pam.d/su 文件,找到#auth required /lib/security/$ISA/pam_wheel.so use_uid这一行,将行首的#去掉。

2)修改 /etc/login.defs 文件,在最后一行增加SU_WHEEL_ONLY yes语句。 然后,用usermod -G wheel 用户名将一个用户添加到wheel组中。 然后,用刚刚被添加到wheel组的用户登录,并执行su命令登录为root用户.这时,输入了正确的root密码可以正常的登录为root用户。但是,如果换成一个不属于wheel组的用户时,执行了su命令后,即使输入了正确的root密码,也无法登录为root用户--普通用户登录为root用户的权限被完全剥夺了(会收到密码错误的提示)。这样无疑提高了系统的安全性.

Ubuntu

adduser example_user
adduser example_user sudo

Debian

apt-get install sudo
adduser example_user
adduser example_user sudo

添加完新用户后执行 exit 退出登录服务器。

使用你的新用户身份登录SSH ssh example_user@203.0.113.10

几乎所有指令都可以使用sudo执行,比如sudo iptables -L -nv,这些指令都会被记录至/var/log/auth.log

第三步 - SSH安全配置

默认情况,我们使用账号密码登录服务器,但使用密钥对替代密码登录更加安全,因为这种方式很难被暴力破解。因此,我们可以创建一个密钥对,然后将SSH的密码登录方式关闭。

创建登录密钥对

  1. 创建密钥对需要在你的本地进行,而不是服务器上,我们需要创建一个4096字节的RSA键值对,在创建过程中,你可以选择是否使用密码来加密私钥。除非你保存私钥到本地电脑上的keychain管理器中,否则你无法通过不输入密码来使用密钥对。建议使用带密码的密钥对。

Linux / OS X

这个命令将会覆盖已经创建的RSA密钥对,如果你已经创建了密钥对可以跳过此步骤,你可以通过ls ~/.ssh/id_rsa* 命令来查看已经存在的密钥。

ssh-keygen -b 4096

输入密码前,在/home/your_username/.ssh按下回车,使用默认名称 id_rsaid_rsa.pub Windows

使用PuTTY生成密钥对.

  1. 上传生成的公钥至你的服务器。

Linux

ssh-copy-id example_user@203.0.113.10

OS X

# 使用你的普通用户身份登录服务器
mkdir -p ~/.ssh && sudo chmod -R 700 ~/.ssh/
# 本地电脑运行
scp ~/.ssh/id_rsa.pub example_user@203.0.113.10:~/.ssh/authorized_keys

Windows

  • 选择一:使用WinSCP 使用账号密码连接服务器.上传公钥至用户主目录 /home/example_user/.ssh/authorized_keys
  • 选择二:直接在Putty中复制生成的公钥,运行下面的指令:

mkdir ~/.ssh; nano ~/.ssh/authorized_keys

创建一个名为authorized_keys的空文件,然后将公钥复制到此文件中,保存退出。

最后你需要为公钥设置权限:

这个步骤千万不要省略!

这个步骤千万不要省略!

这个步骤千万不要省略!

重要的事情说三遍!

  1. sudo chmod 700 -R ~/.ssh && chmod 600 ~/.ssh/authorized_keys

此命令可以阻止其他登录用户获取此文件。

PS: 这个步骤一定不能少,我就出现过两个用户共用一个公钥,结果其中一个可以正常登录,另一个就是登录不上去的情况。如果你也发现这种问题,一定要检查这两个文件的权限!!!

  1. 现在退出服务器,注意:你在登录时需要输入你为你的私钥设置的密码。

SSH守护进程配置

  1. 禁止root用户通过SSH登录。

是否允许root用户通过ssh登录,是通过操作sshd_config配置文件来实现的。当一个ssh连接建立时,操作系统会检查相关文件的配置信息,从而决定是否接受该连接。

# 打开文件 /etc/ssh/sshd_config
vim /etc/ssh/sshd_config
# 找到这一行文字,去掉前面的注释
#PermitRootLogin no
  1. 关闭SSH密码认证。

这要求所有用户必须使用密钥对来登录SSH。

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no

注意:如果你需要从很多不同的设备上登录服务器,你就需要将密码登录的方式开启,这样就不需要再每台电脑上都生成密钥对并上传公钥到服务器。

  1. 只监听一个Internet协议。

SSH 守护进程将同时监听来自IPv4和IPv6的入站连接。除非特殊情况,你只需要保留其一即可。此操作不会影响到系统的其他服务,只针对SSH的守护进程。

使用下面的配置选项:

  • AddressFamily inet用于只监听IPv4
  • AddressFamily inet6用于只监听IPv6

AddressFamily 配置默认不在sshd_config文件中,你可以运行下面的命令追加此配置:

echo 'AddressFamily inet' | sudo tee -a /etc/ssh/sshd_config
  1. 重启SSH,使配置生效。
# CentOS 7, Debian 8, Fedora, Ubuntu 15.10+
sudo systemctl restart sshd
# CentOS 6, Debian 7, Ubuntu 14.04
sudo service ssh restart
# 或者
/etc/init.d/sshd restart

使用Fail2Ban 来保护SSH登录

Using Fail2ban to Secure Your Server

如何使用 fail2ban 防御 SSH 服务器的暴力破解攻击

Fail2Ban 可以禁止尝试登陆你的服务器失败次数过多的IP地址。因为正常的登录失败次数不会超过三次(使用SSH密钥对的方式甚至不会超过一次)。Fail2Ban 可以监控诸如SSH,HTTP以及SMTP协议,默认情况下,Fail2Ban只会监控SSH。

原理:Fail2ban可以监视你的系统日志,然后匹配日志的错误信息(正则表达式匹配)执行相应的屏蔽动作(一般情况下是调用防火墙屏蔽)。比如有人在试探你的SSH、SMTP、FTP密码,只要达到你预设的次数,fail2ban就会调用防火墙屏蔽这个IP,而且可以发送e-mail通知系统管理员。

注意:操作Fail2ban的步骤需要使用root或者sudo权限。

1. 安装Fail2ban

CentOS 7

yum update
# 开启EPEL
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
# 安装Fail2ban
yum install fail2ban
# 安装sendmail
yum install sendmail
# 开启服务
systemctl start fail2ban
systemctl enable fail2ban
systemctl start sendmail
systemctl enable sendmail

Debian

apt-get update && apt-get upgrade -y
apt-get install fail2ban
apt-get install sendmail-bin sendmail

Fedora

dnf update
dnf install fail2ban
dnf install sendmail
systemctl start fail2ban
systemctl enable fail2ban
systemctl start sendmail
systemctl enable sendmail

Ubuntu

apt-get update && apt-get upgrade -y
apt-get install fail2ban
apt-get install sendmail
# 确保UFW 可以使用
ufw enable
ufw allow ssh
2. 配置

Fail2ban 首先读取.conf配置文件,.local文件将会覆盖任何设置。因此,所有变更都在.local文件中修改,.conf应该是保证不可操作的。

fail2ban.local配置

进入 /etc/fail2ban. 所有配置文件都放在此目录中.

cd /etc/fail2ban
# 复制 fail2ban.conf 文件到 fail2ban.local:
cp fail2ban.conf fail2ban.local

打开fail2ban.local,此文件包含Fail2ban日志配置,与守护进程通信的socket,PID文件,可设置的参数值为:

loglevel: Fail2ban 的日志可设置为 1 (error), 2 (warn), 3 (info), 4 (debug).

logtarget: 写入日志的文件可以指定. 默认为 /var/log/fail2ban.log. 你可以将值修改为STDOUT 来输出所有数据; STDERR, 只会输出错误离职; SYSLOG, 记录消息日志;FILE, 将日志写入至文件中.

socket: socket 文件地址.

pidfile: PID 文件地址.

jail.local基本配置

进入/etc/fail2ban,复制文件jail.confjail.local:

cp jail.conf jail.local
# CentOS or Fedora, 设置jail.local中的backend 为 systemd.如果使用Debian 8跳过此步.
vim /etc/fail2ban/jail.local
backend = systemd

IP白名单

添加任何IP至ignoreip都可以将其设置为忽略,默认情况此命令不会禁止localhost,如果你经常从一个IP地址登录,你可以将其设置到忽略列表中

vim /etc/fail2ban/jail.local

[DEFAULT]

# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not
# ban a host which matches an address in this list. Several addresses can be
# defined using space separator.
ignoreip = 127.0.0.1/8 123.45.67.89
# 替换JAIL
fail2ban-client set JAIL addignoreip 123.45.67.89

设置屏蔽时间和重试次数

bantime, findtime, 以及 maxretry三个参数用于配置账号密码尝试登录时的屏蔽时间和重试次数,

# "bantime" is the number of seconds that a host is banned.
bantime  = 600
    
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 600
maxretry = 3
# 注意,postfix也不需要修改这个参数
mta = sendmail
# 修改action 才能发送邮件
action = %(action_mwl)s
  • bantime: 被封IP禁止访问的时间,设定值为24小时,单位是秒,设置为负数表示永久禁止。 默认值为600,表示屏蔽10分钟。
  • findtime: 检测时间,在此时间内超过规定的次数会激活fail2ban,单位是秒。
  • maxretry: 允许错误登录的最大次数,和findtime配合使用。默认值是 3.
  • action: 触发fail2ban采取的动作,action_mwl为禁IP+发通知邮件+写入日志。

Email 提示

  • destemail: 接收Email提示的地址.
  • sendername: 发送Email的名称.
  • sender: 发送Email的的邮箱地址.

如果你不确定sender邮箱地址, 可以执行 sendmail -t user@email.com, 将 user@email.com 替换为你的邮箱地址. 检测收件箱 (包括垃圾邮件) 查看 sender 邮箱地址.

Jail 配置

打开/etc/fail2ban/jail.local

[ssh]
    
enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 6
  • enabled: 决定 filter 是否开启.
  • port: 相关服务的端口. 如果使用默认端口,如果使用默认端口,可以将服务名放在此处,如果不是使用传统的端口,这里需要写入端口号,比如 3456.
  • filter: 此名称对应了 /etc/fail2ban/filter.d中,用于匹配失败登录信息的正则文件名。.conf后缀名省略。
  • logpath: 服务日志路径.

使用Fail2ban Client

fail2ban-client COMMAND
  • start: 开启 Fail2ban 服务和 jails.
  • reload: 重新加载 Fail2ban’s 配置文件.
  • reload JAIL: 重新加载对应的jail.
  • stop: 终止服务.
  • status: 显示服务状态和开启的jails.
  • status JAIL: 显示指定 jail的状态, 包括当前禁止的IP地址.
# 检测fail2ban是否成功运行
fail2ban-client ping

# 查看SSH服务监护状态,能看到当前被禁IP。
fail2ban-client status sshd

# 在SSH监护服务忽略IP列表(白名单)中添加IP 192.168.111.111
fail2ban-client set sshd addignoreip 192.168.111.111

# 在SSH监护服务忽略IP列表(白名单)中删除IP 192.168.111.111
fail2ban-client set sshd delignoreip 192.168.111.111

# 查看fail2ban日志
tail /var/log/fail2ban.log

检查fail2ban状态并解禁被锁住的IP地址

$ sudo iptables --list -n

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
fail2ban-SSH  tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
 
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
 
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
 
Chain fail2ban-SSH (1 references)
target     prot opt source               destination
DROP       all  --  192.168.1.8          0.0.0.0/0
RETURN     all  --  0.0.0.0/0            0.0.0.0/0

如果你想要从fail2ban中解锁某个IP地址,你可以使用iptables命令:

sudo iptables -D fail2ban-SSH -s 192.168.1.8 -j DROP

fail2ban 可以和Nginx结合在一起,进行简单的DDOS防御

(fail2ban读取nginx日志禁止非法ip访问)[http://www.2cto.com/Article/201406/310910.html]

第四步 - 移除不需要的网络服务

大多数Linux发行版会安装运行服务所需的进站连接网络服务,比如Internet,Loopback Interface(回环接口,可允许运行在同一台主机上的程序和服务器程序通过TCP/IP进行通讯。)等。

确定已经运行的服务

$ sudo netstat -tulpn

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      7315/rpcbind
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3277/sshd
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      3179/exim4
tcp        0      0 0.0.0.0:42526           0.0.0.0:*               LISTEN      2845/rpc.statd
tcp6       0      0 :::48745                :::*                    LISTEN      2845/rpc.statd
tcp6       0      0 :::111                  :::*                    LISTEN      7315/rpcbind
tcp6       0      0 :::22                   :::*                    LISTEN      3277/sshd
tcp6       0      0 ::1:25                  :::*                    LISTEN      3179/exim4
udp        0      0 127.0.0.1:901           0.0.0.0:*                           2845/rpc.statd
udp        0      0 0.0.0.0:47663           0.0.0.0:*                           2845/rpc.statd
udp        0      0 0.0.0.0:111             0.0.0.0:*                           7315/rpcbind
udp        0      0 192.0.2.1:123           0.0.0.0:*                           3327/ntpd
udp        0      0 127.0.0.1:123           0.0.0.0:*                           3327/ntpd
udp        0      0 0.0.0.0:123             0.0.0.0:*                           3327/ntpd
udp        0      0 0.0.0.0:705             0.0.0.0:*                           7315/rpcbind
udp6       0      0 :::111                  :::*                                7315/rpcbind
udp6       0      0 fe80::f03c:91ff:fec:123 :::*                                3327/ntpd
udp6       0      0 2001:DB8::123           :::*                                3327/ntpd
udp6       0      0 ::1:123                 :::*                                3327/ntpd
udp6       0      0 :::123                  :::*                                3327/ntpd
udp6       0      0 :::705                  :::*                                7315/rpcbind
udp6       0      0 :::60671                :::*                                2845/rpc.statd

TCP

查看Local Address (本地地址)这一列,rpcbind 进程监听0.0.0.0:111:::111 以及外部地址 0.0.0.0:* , :::* . 这意味着,rpcbind接收来自其它任意IP地址上RPC客户端的TCP连接,不管是IPv4还是IPv6地址,抑或是任意的端口及网络接口。我们可以看到SSH也是如此,而Exim监听来自回环接口的本地IP127.0.0.1的流量。

UDP

UDP Sockets是无状态的, 意味着他们要么是开启要么是关闭,每个进程的连接并不依赖于这些服务本身是否正在工作。对比TCP连接,它并没有诸如LISTEN, ESTABLISHED 和 CLOSE_WAIT这些状态。

netstat输出NTPdate进程显示:

  1. 接收来自某个指定公网IP的进站连接。
  2. 通过localhost通信。
  3. 接收来自外部资源的连接,支持IPv4 和 IPv6,连接端口正在123。

确定需要移除的服务

如果你使用NMap 扫描一个没有安装防火墙的服务器,将会显示SSH,RPC和NTPdate使用的端口是否开启,通过设置防火墙你可以过滤这些端口,但SSH会出现异常,因为它必须允许进站连接,理想情况下,我们应该移除的是不使用的服务。

  • 通常管理员主要通过SSH连接服务器,因此SSH服务必须保留。
  • NTP是用来保证服务器时间与NTPdate保持一致。如果你想要通过异步的方法保障时间或是你不需要精确到纳秒级别的时间,你可以选择关闭此网络端口,然后使用OpenNTPD替代。
  • Exim和RPC,并不是必须的服务,你可以移除它们。

卸载监听的服务

Arch

sudo pacman -Rs package_name

CentOS

sudo yum remove package_name

Debian / Ubuntu

sudo apt-get purge package_name

Fedora

sudo dnf remove package_name

使用sudo netstat -tulpn检查服务。

第五步 - 防火墙配置

使用防火墙来屏蔽一些不要的进站流量,最佳实践是指定你需要的流量,同时阻止其他一切流量。

Iptables通常默认安装,使用起来比较复杂,FirewallD是Fedora系统下的防火墙。

查看你当前的iptables规则

# IPv4
sudo iptables -L -nv
# IPv6
sudo ip6tables -L -nv

Iptables 默认情况下是允许任何的入站、转发以及出站流量。

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

iptables中IPv4和IPv6的基本规则集

以下示例是为一个web 服务器设置的规则:

注意: 一个真实web服务环境可能需要的规则更多或者更少,这些规则也不适用于一个单独的文件或者数据库服务,VPN服务。Iptables规则可以随时修改和重置。

IPv4

打开/tmp/v4:

*filter

# Allow all loopback (lo0) traffic and reject traffic
# to localhost that does not originate from lo0.
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -s 127.0.0.0/8 -j REJECT

# Allow ping.
-A INPUT -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT

# Allow SSH connections.
-A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

# Allow HTTP and HTTPS connections from anywhere
# (the normal ports for web servers).
-A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
-A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

# Allow inbound traffic from established connections.
# This includes ICMP error returns.
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Log what was incoming but denied (optional but useful).
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 7

# Reject all other inbound.
-A INPUT -j REJECT

# Log any traffic that was sent to you
# for forwarding (optional but useful).
-A FORWARD -m limit --limit 5/min -j LOG --log-prefix "iptables_FORWARD_denied: " --log-level 7

# Reject all traffic forwarding.
-A FORWARD -j REJECT

COMMIT

使用Linode的监控服务Longview 还需要加入如下规则允许HTTP和HTTPS连接:

# Allow incoming Longview connections.
-A INPUT -s longview.linode.com -m state --state NEW -j ACCEPT

# Allow incoming NodeBalancer connections.
-A INPUT -s 192.168.255.0/24 -m state --state NEW -j ACCEPT

IPv6

如果你还想要补充IPv6规则,以下示例将会允许HTTP/S以及所有的ICMP方法:

打开文件/tmp/v6

*filter

# Allow all loopback (lo0) traffic and reject traffic
# to localhost that does not originate from lo0.
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -s ::1/128 -j REJECT

# Allow ICMP
-A INPUT -p icmpv6 -j ACCEPT

# Allow HTTP and HTTPS connections from anywhere
# (the normal ports for web servers).
-A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
-A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

# Allow inbound traffic from established connections.
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Log what was incoming but denied (optional but useful).
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables_INPUT_denied: " --log-level 7

# Reject all other inbound.
-A INPUT -j REJECT

# Log any traffic that was sent to you
# for forwarding (optional but useful).
-A FORWARD -m limit --limit 5/min -j LOG --log-prefix "ip6tables_FORWARD_denied: " --log-level 7

# Reject all traffic forwarding.
-A FORWARD -j REJECT

COMMIT

注意: 使用命令apt-get update时,APT 试图解析镜像的域名至IPv6的地址. 如果你选择屏蔽所有的 IPv6, 这会导致Debian和Ubuntu系统在更新时速度很慢,因为APT一直在等待解析至超时。

解决方法: 删除/etc/gai.conf文件中 ::ffff:0:0/96 100 的注释 .

Arch Linux

  1. 创建文件 /etc/iptables/iptables.rules/etc/iptables/ip6tables.rules.
  2. 导入规则:
sudo iptables-restore < /etc/iptables/iptables.rules
sudo ip6tables-restore < /etc/iptables/ip6tables.rules
  1. Arch下的Iptables 默认没有开启. 可以使用 systemd 开启服务:
sudo systemctl start iptables && sudo systemctl start ip6tables
sudo systemctl enable iptables && sudo systemctl enable ip6tables

iptables

Simple Stateful Firewall

CentOS / Fedora

CentOS 6 或者 Fedora 19以下的版本

  1. 创建文件/tmp/v4/tmp/v6。并将上面的示例规则复制到文件中
  2. 导入规则
sudo iptables-restore < /tmp/v4
sudo ip6tables-restore < /tmp/v6
  1. 保存规则:
sudo service iptables save
sudo service ip6tables save
  1. 移除暂时创建的规则文件
sudo rm /tmp/{v4,v6}

CentOS 7 或者 Fedora 20 以上的版本

FirewallID取代直接操作iptables规则的方式设置防火墙, [Introduction to FirewallD on CentOS]https://www.linode.com/docs/security/firewalls/introduction-to-firewalld-on-centos

  1. 如果你想直接操作iptables,你需要关闭FireWallID
sudo systemctl stop firewalld.service && sudo systemctl disable firewalld.service
  1. 安装并开启iptables-services
sudo yum install iptables-services
sudo systemctl enable iptables && sudo systemctl enable ip6tables
sudo systemctl start iptables && sudo systemctl start ip6tables
  1. 创建/tmp/v4/tmp/v6,复制以上示例规则
  2. 导入规则:
sudo iptables-restore < /tmp/v4
sudo ip6tables-restore < /tmp/v6
  1. 保存:
sudo service iptables save
sudo service ip6tables save
  1. 移除暂时创建的规则文件:
sudo rm /tmp/{v4,v6}

CentOS Wiki: iptables

Fedora Project Wiki: FirewallD

Fedora Project Wiki: How to Edit iptables Rules

Red Hat Security Guide: Using Firewalls

Debian / Ubuntu

UFW在Ubuntu系统中可以替代iptables作为防火墙使用。

How to Configure a Firewall with UFW

  1. 创建/tmp/v4/tmp/v6,复制以上示例规则
  2. 导入规则:
sudo iptables-restore < /tmp/v4
sudo ip6tables-restore < /tmp/v6
  1. 安装Iptables-persistent实现自动化加载iptables.
sudo apt-get install iptables-persistent
  1. 输入yes保存当前的IPv4 和IPv6规则
  2. 移除暂时创建的规则文件:
sudo rm /tmp/{v4,v6}

验证iptables 规则

sudo iptables -vL
sudo ip6tables -vL

IPv4输出:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
    0     0 REJECT     all  --  !lo    any     loopback/8           anywhere             reject-with icmp-port-unreachable
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp destination-unreachable
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp echo-request
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere             icmp time-exceeded
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh state NEW
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:http state NEW
    0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:https state NEW
    0     0 ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
    0     0 LOG        all  --  any    any     anywhere             anywhere             limit: avg 5/min burst 5 LOG level debug prefix "iptables_INPUT_denied: "
    0     0 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 LOG        all  --  any    any     anywhere             anywhere             limit: avg 5/min burst 5 LOG level debug prefix "iptables_FORWARD_denied: "
    0     0 REJECT     all  --  any    any     anywhere             anywhere             reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

IPv6输出:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all      lo     any     anywhere             anywhere
    0     0 REJECT     all      !lo    any     localhost            anywhere             reject-with icmp6-port-unreachable
    0     0 ACCEPT     ipv6-icmp    any    any     anywhere             anywhere
    0     0 ACCEPT     tcp      any    any     anywhere             anywhere             tcp dpt:http state NEW
    0     0 ACCEPT     tcp      any    any     anywhere             anywhere             tcp dpt:https state NEW
    0     0 ACCEPT     all      any    any     anywhere             anywhere             state RELATED,ESTABLISHED
    0     0 LOG        all      any    any     anywhere             anywhere             limit: avg 5/min burst 5 LOG level debug prefix "ip6tables_INPUT_denied: "
    0     0 REJECT     all      any    any     anywhere             anywhere             reject-with icmp6-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 LOG        all      any    any     anywhere             anywhere             limit: avg 5/min burst 5 LOG level debug prefix "ip6tables_FORWARD_denied: "
    0     0 REJECT     all      any    any     anywhere             anywhere             reject-with icmp6-port-unreachable

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

iptables 规则操作

Iptables rules are enforced in a top-down fashion, so the first rule in the ruleset is applied to traffic in the chain, then the second, third and so on. This means that rules cannot necessarily be added to a ruleset with iptables -A or ip6tables -A. Instead, rules must be inserted with iptables -I or ip6tables -I.

参数

 -A或者--append         //将一条或多条规则加到链尾
 -D或者--delete        //从链中删除该规则、 -R或者--replace   //从所选链中替换一条规则
 -L或者--list          //显示链的所有规则
 -I或者--inset         //根据给出的规则序号,在链中插入规则。按序号的顺序插入,如是 “1”就插入链首
 -X或者--delete-chain  //用来删除用户自定义链中规则。必须保证链中的规则都不在使用时才能删除链。如没有指定链,将删除所有自定义链中的规则。
 -F或者--flush         //清空所选链中的所有规则。如指定链名,则删除对应链的所有规则。如没有指定链名,则删除所有链的所有规则。
 -N或者--new-chain     //用命令中所指定的名字创建一个新链。
 -P或者--policy        //设置链的默认目标,即策略。 与链中任何规则都不匹配的信息包将强制使用此命令中指定的策略。
 -Z或者--zero          //将指定链中的所有规则的包字节计数器清零。

插入

# 查询已存在的IP规则
sudo iptables -L -nv --line-numbers
# 示例
sudo iptables -I INPUT 9 -p tcp --dport 8080 -j ACCEPT

替换

sudo iptables -R INPUT 11 -m limit --limit 3/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 7

删除

sudo iptables -D INPUT 9

第六步 - Linux 系统设置、Bash以及内核参数调优等

历史记录数以及登录超时环境变量设置

  1. 设置闲置账号超时时间
# 临时配置
$ export TMOUT=10
  1. 设置Linux的命令行历史记录数
# 临时设置
$ export HISTSIZE=5

设定命令行的历史记录文件(~/.bash_history)记录指定命令数量

# 临时设置
export HISTFILESIZE=5
cat ~/.bash_history
  1. 写入配置,永久生效
$ echo 'export TMOUT=300'>>/etc/profile
$ echo 'export HISTSIZE=10' >> /etc/profile
$ echo 'export HISTFILESIZE=25' >> /etc/profile
$ tail -3 /etc/profile
export TMOUT=300
export HISTSIZE=10
export HISTFILESIZE=25
$ source /etc/profile

调整系统文件描述符

方法一:

vim /etc/security/limits.conf
# 最后一行加入
* - nofile 102488
# 或者
echo '* - nofile 102488' >> /etc/security/limits.conf
tail -1 /etc/security/limits.conf
# 重新登录SSH

方法二:

ulimit -SHn 65535 加入 etc/rc.local,每次开机启动时配置生效:

cat >> /etc/rc.local << EOF
> # -S use the 'soft' resource limit
> # -H use the 'hard' resource limit
> # -n the maximun number of open file descriptiors
> ulimit -HSn 65535
> # -s the max stack size
> ulimit -s 65535
> EOF

内核参数优化

net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 4000 65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
net.ipv4.tcp_timestamps = 0
# 针对iptables防火墙优化
net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60

执行生效命令

$ sysctl -p
net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 4000 65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
net.ipv4.tcp_timestamps = 0
net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60

定时清理邮件临时目录垃圾文件

# 删除垃圾文件指令,适用于postfix
 find /var/spool/postfix/maildrop/ -type f|xargs rm -f

将上述命令写成脚本定时执行一次

$ mkdir -p /server/scripts
$ echo 'find /var/spool/postfix/maildrop/ -type f|xargs rm -f' > /server/scripts/del_file.sh
$ cat /server/scripts/del_file.sh
find /var/spool/postfix/maildrop/ -type f|xargs rm -f
# 使用root身份执行命令
$ echo "00 00 * * * /bin/sh /server/scripts/del_file.sh > /dev/null 2>&1" >> /var/spool/cron/root
$ crontab -l
00 00 * * * /bin/sh /server/scripts/del_file.sh > /dev/null 2>&1

锁定关键系统文件,防止被提权篡改

# 上锁后,所有用户都不能对文件进行修改
chattr +i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/inittab
# 解锁命令
chattr -i /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/inittab
# 上锁后,如果需要临时操作,可以解锁后对文件进行修改,之后再上锁
# 如果想更安全,可以把chattr改名转移
$ mv /usr/bin/chattr /usr/bin/damonfutan
$ chattr -i /etc/passwd
-bash: /usr/bin/chattr: No such file or directory

Linux的chattr与lsattr命令详解