Linux加固手册

本文总结Linux系统及服务组件安全加固方法...

0x01 Linux 系统加固

1. 账号和口令

1.1 禁用或删除无用账号

减少系统无用账号,降低安全风险

操作步骤

  • 使用命令 userdel <用户名> 删除不必要的账号
  • 使用命令 passwd -l <用户名> 锁定不必要的账号
  • 使用命令 passwd -u <用户名> 解锁必要的账号

1.2 检查特殊账号

检查是否存在空口令和root权限的账号

操作步骤

  1. 查看空口令和root权限账号,确认是否存在异常账号:
  • 使用命令 awk -F: '($2=="")' /etc/shadow 查看空口令账号
  • 使用命令 awk -F: '($3==0)' /etc/passwd 查看UID为零的账号
  1. 加固空口令账号:
  • 使用命令 passwd <用户名> 为空口令账号设定密码
  • 确认UID为零的账号只有root账号

1.3 添加口令策略

加强口令的复杂度等,降低被猜解的可能性

操作步骤

  1. 使用命令 vi /etc/login.defs 修改配置文件

     PASS_MAX_DAYS 90     #新建用户的密码最长使用天数
     PASS_MIN_DAYS 0       #新建用户的密码最短使用天数
     PASS_WARN_AGE 7     #新建用户的密码到期提前提醒天数
    
  2. 使用chage命令修改用户设置

     chage -m 0 -M 30 -E 2000-01-01 -W 7 <用户名>
    

    表示将此用户的密码最长使用天数设为30,最短使用天数设为0,密码2000年1月1日过期,过期前七天警告用户

  3. 设置连续输错三次密码,账号锁定五分钟

    使用命令 vi /etc/pam.d/common-auth修改配置文件,在配置文件中添加 auth required pam_tally.so onerr=fail deny=3 unlock_time=300

1.4 限制用户su

限制能su到root的用户

操作步骤

使用命令 vi /etc/pam.d/su修改配置文件,在配置文件中添加行

只允许test组用户su到root,则添加auth required pam_wheel.so group=test

1.5 禁止root用户直接登录

限制root用户直接登录

操作步骤

  1. 创建普通权限账号并配置密码,防止无法远程登录;
  2. 使用命令 vi /etc/ssh/sshd_config修改配置文件将PermitRootLogin的值改成no,并保存,然后使用service sshd restart重启服务

2. 服务加固

2.1 关闭不必要的服务

关闭不必要的服务(如普通服务和xinetd服务),降低风险

操作步骤

使用命令systemctl disable <服务名>设置服务在开机时不自动启动

CentOS 6可以使用命令chkconfig --level <init级别> <服务名> off设置服务在指定init级别下开机时不自动启动。

2.2 SSH服务安全

对SSH服务进行安全加固,防止暴力破解成功

操作步骤

使用命令 vim /etc/ssh/sshd_config 编辑配置文件

  1. 不允许root账号直接登录系统: 设置 PermitRootLogin 的值为 no
  2. 修改SSH使用的协议版本: 设置 Protocol 的版本为 2
  3. 修改允许密码错误次数(默认6次): 设置 MaxAuthTries 的值为 3
  配置文件修改完成后,重启sshd服务生效。

3. 文件系统

3.1 设置umask值

设置默认的umask值,增强安全性

操作步骤

使用命令 vi /etc/profile 修改配置文件,添加行 umask 027, 即新创建的文件属主拥有读写执行权限,同组用户拥有读和执行权限,其他用户无权限。

3.2 设置登录超时

设置系统登录后,连接超时时间,增强安全性

操作步骤

使用命令 vi /etc/profile 修改配置文件,将以 TMOUT= 开头的行注释,设置为TMOUT=180,即超时时间为三分钟

4. 日志

4.1 syslogd日志

启用日志功能,并配置日志记录

操作步骤

Linux系统默认启用以下类型日志:

系统日志(默认)/var/log/messages
cron日志(默认)/var/log/cron
安全日志(默认)/var/log/secure
注意:部分系统可能使用`syslog-ng`日志,配置文件为:`/etc/syslog-ng/syslog-ng.conf`

4.2 登录和操作日志

通过脚本代码实现记录所有用户的登录操作日志,防止出现安全事件后无据可查

操作步骤

运行 [root@xxx /]# vim /etc/profile打开配置文件

在配置文件中输入以下内容:

history
USER=`whoami`
USER_IP=`who -u am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`
if [ "$USER_IP" = "" ]; then
USER_IP=`hostname`
fi
if [ ! -d /var/log/history ]; then
mkdir /var/log/history
chmod 777 /var/log/history
fi
if [ ! -d /var/log/history/${LOGNAME} ]; then
mkdir /var/log/history/${LOGNAME}
chmod 300 /var/log/history/${LOGNAME}
fi
export HISTSIZE=4096
DT=`date +"%Y%m%d_%H:%M:%S"`
export HISTFILE="/var/log/history/${LOGNAME}/${USER}@${USER_IP}_$DT"
chmod 600 /var/log/history/${LOGNAME}/*history* 2>/dev/null

运行 [root@xxx /]# source /etc/profile 加载配置生效

注意: /var/log/history 是记录日志的存放位置,可以自定义

通过上述步骤,可以在/var/log/history目录下以每个用户为名新建一个文件夹,每次用户退出后都会产生以用户名、登录IP、时间的日志文件,包含此用户本次的所有操作(root用户除外)

0x02 Rsync 服务安全加固

Rsync 是一个通过检查文件的时间戳和大小,来跨计算机系统高效地传输和同步文件的工具

通常情况下,管理程序在启动 Rsync 服务后,会直接运行传输任务。如果 Rsync 服务未经过安全加固,则很容易出现未授权访问等安全问题;其直接后果是传输数据裸露在互联网上,可以被任何人访问获取,带来严重的数据泄露风险

建议在使用 Rsync 服务端时,对 Rsync 服务进行安全加固,保障数据安全

1. 隐藏 module 信息

将配置文件修改为以下内容:

list = false

2. 使用权限控制

将不需要写入权限的 module 设置为只读:

read only = true

3. 限制网络访问

使用 安全组策略 或白名单,限制允许访问主机的 IP 地址

hosts allow = 10.10.10.10

4. 启用账户认证

只允许指定的用户,使用指定的密码,来调用 Rsync 服务

服务端配置

auth users = ottocho
secrets file = /etc/rsyncd.secrets

在文件 /etc/rsyncd.secrets 中写入使用的账号密码(可自行选择),格式为:username:password,支持多行

注意:密码要求满足强密码策略,必须是 8 位以上,且包括大小写字母、数字、特殊字符的字符串;此处的 password 使用明文

客户端配置

在客户端,使用 --password-file=/etc/rsyncd.secrets 参数,在 /etc/rsyncd.secrets 中写入密码

Rsync -av --password-file=/etc/rsyncd.secrets test.host.com::files /des/path

在上述 /etc/rsyncd.secrets 密码文件中,用户或用户组必须和实际使用者保持一致,且权限必须是 600

5. 数据加密传输

Rsync 默认不支持加密传输,如果需要使用 Rsync 传输重要性很高的数据,可以使用 SSH 模式

Rsync 支持以下两种同步模式:

  • 当源路径或目的路径的主机名后面包含一个冒号分隔符时,Rsync 使用 SSH 传输
  • 当源路径或目的路径的主机名后面包含两个冒号,或使用 Rsync://URL 时,Rsync 使用 TCP 直接连接 Rsync daemon

在配置好 SSH 后,推荐参照以下方式来使用:

Rsync -av test.host.com:/path/to/files /des/path

0x03 NFS 服务安全加固

NFS(Network File System)是 FreeBSD 支持的一种文件系统,它允许网络中的计算机之间通过 TCP/IP 网络共享资源。不正确的配置和使用 NFS,会带来安全问题

缺陷总结

NFS 的不安全性,主要体现于以下 4 个方面:

1)缺少访问控制机制
2)没有真正的用户验证机制,只针对 RPC/Mount 请求进行过程验证
3)较早版本的 NFS 可以使未授权用户获得有效的文件句柄
4)在 RPC 远程调用中, SUID 程序具有超级用户权限

1. 配置共享目录(/etc/exports)

使用 anonuid,anongid 配置共享目录,这样可以使挂载到 NFS 服务器的客户机仅具有最小权限。不要使用 no_root_squash

2. 使用网络访问控制

使用 安全组策略 或 iptable 防火墙限制能够连接到 NFS 服务器的机器范围

iptables -A INPUT -i eth0 -p TCP -s 172.16.0.0/12 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p UDP -s 172.16.0.0/12 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p TCP -s 10.0.0.0/8 --dport 111 -j ACCEPT
iptables -A INPUT -i eth0 -p UDP -s 10.0.0.0/8 --dport 111 -j ACCEPT

3. 账号验证

使用 Kerberos V5 作为登录验证系统,要求所有访问人员使用账号登录,提高安全性

4. 设置 NFSD 的 COPY 数目

在 Linux 中,NFSD 的 COPY 数目定义在启动文件 /etc/rc.d/init.d/nfs 中,默认值为 8

最佳的 COPY 数目一般取决于可能的客户机数目。可以通过测试来找到 COPY 数目的近似最佳值,并手动设置该参数

5. 选择传输协议

对于不同的网络情况,有针对地选择 UDP 或 TCP 传输协议。传输协议可以自动选择,也可以手动设置

mount -t nfs -o sync,tcp,noatime,rsize=1024,wsize=1024 EXPORT_MACHINE:/EXPORTED_DIR /DIR

UDP 协议传输速度快,非连接传输时便捷,但其传输稳定性不如 TCP,当网络不稳定或者黑客入侵时很容易使 NFS 性能大幅降低,甚至导致网络瘫痪。一般情况下,使用 TCP 的 NFS 比较稳定,使用 UDP 的 NFS 速度较快

  • 在机器较少,网络状况较好的情况下,使用 UDP 协议能带来较好的性能。
  • 当机器较多,网络情况复杂时,推荐使用 TCP 协议(V2 只支持 UDP 协议)。
  • 在局域网中使用 UDP 协议较好,因为局域网有比较稳定的网络保证,使用 UDP 可以带来更好的性能
  • 在广域网中推荐使用 TCP 协议,TCP 协议能让 NFS 在复杂的网络环境中保持最好的传输稳定性

6. 限制客户机数量

修改 /etc/hosts.allow/etc/hosts.deny 来限制客户机数量

/etc/hosts.allow
portmap: 192.168.0.0/255.255.255.0 : allow
portmap: 140.116.44.125 : allow
/etc/hosts.deny
portmap: ALL : deny

7. 改变默认的 NFS 端口

NFS 默认使用的是 111 端口,使用 port 参数可以改变这个端口值。改变默认端口值能够在一定程度上增强安全性

8. 配置 nosuid 和 noexec

SUID (Set User ID) 或 SGID (Set Group ID) 程序可以让普通用户以超过自己权限来执行。很多 SUID/SGID 可执行程序是必须的,但也可能被一些恶意的本地用户利用,获取本不应有的权限

尽量减少所有者是 root,或是在 root 组中却拥有 SUID/SGID 属性的文件。可以删除这样的文件或更改其属性,如:

  • 使用 nosuid 选项禁止 set-UID 程序在 NFS 服务器上运行,可以在 /etc/exports 加入一行:

      /www www.abc.com(rw, root_squash, nosuid)
    
  • 使用 noexec 禁止直接执行其中的二进制文件。

0x04 Apache 服务安全加固

1. 用户设置

1. 以专门的用户帐号和用户组运行 Apache 服务

根据需要,为 Apache 服务创建用户及用户组。如果没有设置用户和组,则新建用户,并在 Apache 配置文件中进行指定。

1)创建 Apache 用户组。

groupadd apache

2)创建 Apache 用户并加入 Apache 用户组。

useradd apache -g apache

3)将下面两行设置参数加入 Apache 配置文件 httpd.conf 中:

User apache    Group apache

2. 检查 httpd.conf 配置文件中是否允许使用非专用账户(如 root 用户)运行 Apache 服务

默认设置一般即符合要求。Linux 系统中默认使用 apache 或者 nobody 用户,Unix 系统默认使用 daemon 用户

2. 授权设置

1. 严格控制 Apache 主目录的访问权限,非超级用户不能修改该目录中的内容

Apache 的主目录对应于 Apache Server配置文件 httpd.conf 中的 Server Root 控制项,应设置为:

Server Root /usr/local/apache
  • 判定条件: 非超级用户不能修改该目录中的内容。
  • 检测操作: 尝试进行修改,看是否能修改该目录中的内容。

该目录一般设置为 /etc/httpd 目录,默认情况下属主为 root 用户,其它用户不能修改该目录中的文件。默认设置一般即符合要求。

2. 严格设置配置文件和日志文件的权限,防止未授权访问

  • 执行chmod 600 /etc/httpd/conf/httpd.conf命令设置配置文件为属主可读写,其他用户无读写权限。
  • 执行chmod 644 /var/log/httpd/.log命令设置日志文件为属主可读写,其他用户拥有只读权限。

注意:/etc/httpd/conf/httpd.conf 配置文件的默认权限是644,可根据需要修改权限为600。 /var/log/httpd/.log 日志文件的默认权限为644,默认设置即符合要求。

3. 日志设置

Apache 设备应配置日志功能,对运行错误、用户访问等事件进行记录,记录内容包括时间,用户使用的 IP 地址等内容。

修改 httpd.conf 配置文件,设置日志记录文件、记录内容、记录格式。

错误日志:

LogLevel notice #日志的级别    ErrorLog /…/logs/error_log #日志的保存位置(错误日志)

访问日志:

LogFormat %h %l %u %t \”%r\” %>s %b “%{Accept}i\”%{Referer}i\” \”%{User-Agent}i\””    combined    CustomLog /…/logs/access_log combined (访问日志)

注意:

  • ErrorLog指令设置错误日志文件名和位置。错误日志是最重要的日志文件。Apache httpd 程序将在这个文件中存放诊断信息和处理请求中出现的错误。若要将错误日志传送到 Syslog,则执行ErrorLog syslog命令。
  • CustomLog指令指定了保存日志文件的具体位置以及日志的格式。访问日志中会记录服务器所处理的所有请求。
  • LogFormat命令用于设置日志格式,建议设置为 combined 格式。
  • LogLevel命令用于调整记录在错误日志中的信息的详细程度,建议设置为 notice。日志的级别,默认是 warn 级别,notice 级别比较详细,但在实际中由于日志会占用大量硬盘空间。

4. 禁止访问外部文件

禁止 Apache 访问 Web 目录之外的任何文件

1. 修改 httpd.conf 配置文件

Order Deny,Allow    Deny from all

2. 设置可访问的目录

Order Allow,Deny    Allow from /web

说明: 其中 /web 为网站根目录

3. 默认配置如下,可根据业务需要进行设置

Options FollowSymLinks    AllowOverride None

5. 禁止目录浏览

目录浏览会导致明显信息泄露或下载,建议禁止 Apache 列表显示文件。在 /etc/httpd/httpd.conf 配置文件中删除 Options 的 Indexes 设置即可

1. 修改 httpd.conf 配置文件

#Options Indexes FollowSymLinks #删掉Indexes    Options FollowSymLinks    AllowOverride None    Order allow,deny    Allow from all

将Options Indexes FollowSymLinks中的Indexes去掉,就可以禁止 Apache 显示该目录结构。Indexes的作用就是当该目录下没有 index.html 文件时,自动显示目录结构

2. 重新启动 Apache 服务

6. 错误页面重定向

Apache 错误页面重定向功能可以防止敏感信息泄露。

1. 修改 httpd.conf 配置文件

ErrorDocument 400 /custom400.html    ErrorDocument 401 /custom401.html    ErrorDocument 403 /custom403.html    ErrorDocument 404 /custom404.html    ErrorDocument 405 /custom405.html    ErrorDocument 500 /custom500.html

注意: Customxxx.html 为要设置的错误页面

2. 重新启动 Apache 服务

注意: 此项配置需要应用系统设有错误页面,或者不在 httpd 中设置,而完全由业务逻辑实现

7. 拒绝服务防范

根据业务需要,合理设置 session 时间,防止拒绝服务攻击

1. 修改 httpd.conf 配置文件

Timeout 10 #客户端与服务器端建立连接前的时间间隔 KeepAlive On KeepAliveTimeout 15 #限制每个 session 的保持时间是 15 秒。此处为建议值,具体的参数值需要根据现实际情况设定

2. 重新启动 Apache 服务

注意: 默认值为Timeout 120,KeepAlive Off,KeepAliveTimeout 15,该项设置涉及性能调整

8. 隐藏 Apache 版本号

隐藏 Apache 的版本号及其它敏感信息

1. 修改 httpd.conf 配置文件:

ServerSignature Off ServerTokens Prod

9. 关闭 TRACE功能

关闭 TRACE 功能,防止 TRACE 方法被访问者恶意利用。

在 /etc/httpd/conf/httpd.conf 配置文件中添加以下设置参数:

TraceEnable Off

注意: 该参数适用于 Apache 2.0 以上版本

10. 禁用 CGI

如果服务器上不需要运行 CGI 程序,建议禁用 CGI

如果没有CGI程序,可以修改 /etc/httpd/conf/httpd.conf 配置文件,把 cgi-bin 目录的配置和模块都进行注释。

#LoadModule cgi_module modules/mod_cgi.so#ScriptAlias /cgi-bin/ “/var/www/cgi-bin/##AllowOverride None# Options None#Order allow,deny#Allow from all#

11. 绑定监听地址

服务器有多个 IP 地址时,只监听提供服务的 IP 地址

1. 执行以下命令查看是否绑定 IP 地址

cat /etc/httpd/conf/httpd.conf|grep Listen

2. 修改 /etc/httpd/conf/httpd.conf 配置文件

Listen x.x.x.x:80

监听功能默认监听所有地址,如果服务器只有一个 IP 地址可不修改该项设置,如果有多个 IP 可根据需要进行设置

12. 删除缺省安装的无用文件

删除缺省安装的无用文件

  • 删除缺省 HTML 文件:

      rm -rf /usr/local/apache2/htdocs/
    
  • 删除缺省的 CGI 脚本:

      rm -rf /usr/local/apache2/cgi-bin/
    
  • 删除 Apache 说明文件:

      rm -rf /usr/local/apache2/manual
    
  • 删除源代码文件:

      rm -rf /path/to/httpd-2.2.4*
    
  • 删除 CGI

可根据实际情况删除,一般情况下 /var/www/html /var/www/cgi-bin 默认就是空的。

注意: 根据安装步骤不同和版本不同,某些目录或文件可能不存在或位置不同

13. 禁用非法 HTTP 方法

禁用 PUT、DELETE 等危险的 HTTP 方法

修改 httpd.conf 配置文件,只允许 get、post 方法

Order Allow,Deny  Deny from all

可根据需要进行设置,如果需要用到 PUT 或 Delete 等 HTTP 方法的话,在/etc/httpd/conf/httpd.conf 配置文件中相应添加即可

0x05 Tomcat 服务安全加固

通常 Tomcat 后台管理的 URL 地址为 http://iP:8080/manager/html/

Tomcat服务默认启用了管理后台功能,使用该后台可直接上传 war 文件包对站点进行部署和管理。如果管理后台存在空口令或者弱口令的漏洞,使得黑客可以利用该漏洞直接上传 Webshell 脚本导致服务器沦陷

1. 网络访问控制

  • 如果业务不需要使用 Tomcat 管理后台管理业务代码,建议使用安全组防火墙功能对管理后台 URL 地址进行拦截,或直接将 Tomcat 部署目录中 webapps 文件夹中的 manager、host-manager 文件夹全部删除,并注释 Tomcat 目录中 conf 文件夹中的 tomcat-users.xml 文件中的所有代码

  • 如果业务系统确实需要使用 Tomcat 管理后台进行业务代码的发布和管理,建议为 Tomcat 管理后台配置强口令,并修改默认 admin 用户,且密码长度不低于10位,必须包含大写字母、特殊符号、数字组合

2. 开启 Tomcat 的访问日志

修改 conf/server.xml 文件,将下列代码取消注释:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"   
prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>

启用访问日志功能,重启 Tomcat 服务后,在 tomcat_home/logs 文件夹中就可以看到访问日志

3. Tomcat 默认帐号安全

修改 Tomcat 安装目录 conf 下的 tomcat-user.xml 文件,重新设置复杂口令并保存文件。重启 Tomcat 服务后,新口令即生效

4. 修改默认访问端口

修改 conf/server.xml 文件把默认的 8080 访问端口改成其它端口

5. 重定向错误页面

修改访问 Tomcat 错误页面的返回信息,在 webapps\manger 目录中创建相应的401.html、404.htm、500.htm 文件,然后在 conf/web.xml 文件的最后一行之前添加下列代码:

<error-page>  
                    <error-code>401</error-code>      
                    <location>/401.htm</location>  
            </error-page>  
            <error-page>  
                    <error-code>404</error-code>  
                    <location>/404.htm</location>  
            </error-page>  
            <error-page>  
                    <error-code>500</error-code>  
                    <location>/500.htm</location>  
            </error-page>

6. 禁止列出目录

在web.xml文件中,防止直接访问目录时由于找不到默认页面,而列出目录下的文件的情况

listings
false

7. 删除文档和示例程序

删除 webapps 目录下的 docs、examples、manager、ROOT、host-manager 文件夹

0x06 MySQL 服务安全加固

1. 帐号安全

1. 禁止 Mysql 以管理员帐号权限运行

以普通帐户安全运行 mysqld,禁止以管理员帐号权限运行 MySQL 服务。在 /etc/my.cnf 配置文件中进行以下设置。

[mysql.server]
user=mysql

2. 避免不同用户间共享帐号

参考以下步骤

  1. 创建用户

     mysql> mysql> insert into
     mysql.user(Host,User,Password,ssl_cipher,x509_issuer,x509_sub ject) values("localhost","pppadmin",password("passwd"),'','','');
    

执行以上命令可以创建一个 phplamp 用户

  1. 使用该用户登录 MySQL 服务

     mysql>exit;
     @>mysql -u phplamp -p
     @>输入密码
     mysql>登录成功
    

3. 删除无关帐号

DROP USER 语句可用于删除一个或多个 MySQL 账户。使用 DROP USER 命令时,必须确保当前账号拥有 MySQL 数据库的全局 CREATE USER 权限或 DELETE 权限。账户名称的用户和主机部分分别与用户表记录的 User 和 Host 列值相对应

执行DROP USER user;语句,可以取消一个账户和其权限,并删除来自所有授权表的帐户权限记录

2. 口令安全

检查账户默认密码和弱密码。口令长度需要至少八位,并包括数字、小写字母、大写字母和特殊符号四类中的至少两种类型,且五次以内不得设置相同的口令。密码应至少每 90 天进行一次更换

可以通过执行以下命令修改密码

mysql> update user set password=password('test!p3') where user='root';
mysql> flush privileges;

3. 授权

在数据库权限配置能力范围内,根据用户的业务需要,配置其所需的最小权限

1. 查看数据库授权情况

mysql> use mysql;
mysql> select * from user;
mysql>select * from db;
mysql>select * from host;
mysql>select * from tables_priv;
mysql>select * from columns_priv;

2. 通过 revoke 命令回收不必要的或危险的授权

mysql> help revoke
Name: 'REVOKE'
Description:
Syntax:
REVOKE
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type]
{
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
FROM user [, user] ...

4. 开启日志审计功能

数据库应配置日志功能,便于记录运行状况和操作行为

MySQL服务日志类型

错误日志: -log-err
查询日志: -log (可选)
慢查询日志: -log-slow-queries (可选)
更新日志: -log-update
二进制日志: -log-bin

找到 MySQL 的安装目录,在 my.ini 配置文件中增加上述所需的日志类型参数,保存配置文件后,重启 MySQL 服务即可启用日志功能。例如,

#Enter a name for the binary log. Otherwise a default name will be used.
#log-bin=
#Enter a name for the query log file. Otherwise a default name will be used.
#log=
#Enter a name for the error log file. Otherwise a default name will be used.
log-error=
#Enter a name for the update log file. Otherwise a default name will be used.
#log-update=

该参数中启用错误日志。如果您需要启用其他的日志,只需把对应参数前面的 “#” 删除即可。

日志查询操作说明

  • 执行show variables like ‘log_%’;命令可查看所有的 log。
  • 执行show variables like ‘log_bin’;命令可查看具体的 log

5. 安装最新补丁

确保系统安装了最新的安全补丁

注意: 在保证业务及网络安全的前提下,并经过兼容性测试后,安装更新补丁

6. 远程访问控制

禁止网络连接,防止猜解密码攻击、溢出攻击、和嗅探攻击。

注意: 仅限于应用和数据库在同一台主机的情况。

如果数据库不需要远程访问,可以禁止远程 TCP/IP 连接,通过在 MySQL 服务器的启动参数中添加--skip-networking参数使 MySQL 服务不监听任何 TCP/IP 连接,增加安全性。

您可以使用 安全组 进行内外网访问控制,建议不要将数据库高危服务对互联网开放。

7. IP 访问控制

通过数据库所在操作系统的防火墙限制,实现只有信任的 IP 才能通过监听器访问数据库。

mysql> GRANT ALL PRIVILEGES ON db.*
·-> -> TO 用户名@'IP子网/掩码';

8. 连接数设置

根据您的机器性能和业务需求,设置最大、最小连接数

在 MySQL 配置文件(my.conf 或 my.ini)的 [mysqld] 配置段中添加max_connections = 1000,保存配置文件,重启 MySQL 服务后即可生效。

0x07 Redis 服务安全加固

漏洞描述

Redis 因配置不当存在未授权访问漏洞,可以被攻击者恶意利用

在特定条件下,如果 Redis 以 root 身份运行,黑客可以给 root 账号写入 SSH 公钥文件,直接通过 SSH 登录受害服务器,从而获取服务器权限和数据。一旦入侵成功,攻击者可直接添加账号用于 SSH 远程登录控制服务器,给用户的 Redis 运行环境以及 Linux 主机带来安全风险,如删除、泄露或加密重要数据,引发勒索事件等

受影响范围

在 Redis 客户端,尝试无账号登录 Redis:

root@kali:~# redis-cli -h 10.16.10.2
redis 10.16.10.2:6379&gt; keys *

从登录结果可以看出,该 Redis 服务对公网开放,且未启用认证

1.网络层加固

指定 Redis 服务使用的网卡

默认情况下,Redis 监听 127.0.0.1。如果仅仅是本地通信,请确保监听在本地

这种方式可以在一定程度上缓解 Redis 未授权访问的风险(例外情况下,如果 Redis 以 root 用户运行,攻击者借助已有的 webshell,就可以利用该 Redis 来反弹 shell 以实现提权)

在 redis.conf 文件中找到 # bind 127.0.0.1,将前面的 # 去掉,然后保存

注意:

  1. 该操作需要重启 Redis 才能生效。

  2. 修改后只有本机才能访问 Redis,也可以指定访问源 IP 来访问 Redis

    bind 192.168.1.100 10.0.0.1

2.设置防火墙策略

如果正常业务中 Redis 服务需要被其他服务器来访问,可以通过 iptables 策略,仅允许指定的 IP 来访问 Redis 服务

iptables -A INPUT -s x.x.x.x -p tcp --dport 6379 -j ACCEPT

3.账号与认证

设置访问密码

在 redis.conf 中找到 requirepass 字段,去掉其注释,并在后面填上需要的密码。Redis 客户端也需要使用此密码来访问 Redis 服务。

打开 /etc/redis/redis.conf 配置文件:

requirepass MLDk$*091e8331lcfs

确保密码的复杂度,配置完毕后重启服务即可生效

4.服务运行权限最小化

修改 Redis 服务运行账号

请以较低权限账号运行 Redis 服务,并禁用该账号的登录权限。以下操作创建了一个无 home 目录权限,且无法登录的普通账号:

useradd -M -s /sbin/nologin [username]

注意:该操作需要重启 Redis 才能生效

5.服务细粒度授权

隐藏重要命令

Redis 无权限分离,其管理员账号和普通账号无明显区分。攻击者登录后可执行任意操作,因此需要隐藏以下重要命令:FLUSHDB, FLUSHALL, KEYS,PEXPIRE, DEL, CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, SREM, RENAME,DEBUG, EVAL

另外,在 Redis 2.8.1 及 Redis 3.x (低于 3.0.2) 版本下存在 EVAL 沙箱逃逸漏洞,攻击者可通过该漏洞执行任意 Lua 代码。

下述配置将 config/flushdb/flushall 设置为空,即禁用该命令;也可设置为一些复杂的、难以猜测的名字。

rename-command CONFIG ""
rename-command flushall ""
rename-command flushdb ""
rename-command shutdown shotdown_test

保存后,执行 /etc/init.d/redis-server restart 重启生效

6.安全补丁

定期关注最新软件版本,并及时升级 Redis 到最新版,防止新漏洞被恶意利用。

0x08 Elasticsearch服务安全加固

Elasticsearch 是一个基于 Lucene 的搜索服务,它提供了 RESTful web 接口的分布式、多用户全文搜索引擎 。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是第二大最流行的企业搜索引擎

Elasticsearch 应用于云计算中,具有实时搜索、稳定、可靠、快速、安装使用方便等优势;但也存在一些安全隐患:默认安装完成后,Elasticsearch 可以使用 9200 端口通告 web 的方式访问查看数据信息

漏洞详情

Elasticsearch 中存在以下高危漏洞

类型 CVE 受影响版本 描述
远程命令执行 CVE-2014-3120 - Elasticsearch 的脚本执行 (scripting) 功能,可以很方便地对查询出来的数据进行再加工处理。但是,其使用的 MVEL 脚本引擎没有做过任何防护(或者沙盒包装),可以直接执行任意代码
远程代码执行 - 1.3.0-1.3.7,1.4.0-1.4 Elasticsearch 使用 Groovy 作为脚本语言,虽然加入了沙盒进行控制,危险的代码会被拦截。但是由于沙盒限制不严格,仅通过黑白名单来判断,导致攻击者可以绕过沙盒,执行远程代码
未授权访问 - - Elasticsearch 在安装了 River 机制之后可以同步多种数据库数据(包括关系型的MySQL、MongoDB 等)。如果 http://localhost:9200/cat/indices 中 indices 包含了 _river,则代表 Elasticsearch 已安装 River 机制。而通过泄露的 http://localhost:9200/_rvier/_search URL 地址,攻击者可以获取到敏感信息

漏洞成因与危害

由于 Elasticsearch 的 HTTP 连接没有提供任何的权限控制措施,一旦部署在公共网络就容易有数据泄露的风险

1. 使用最新版本

通过Elastic 官网下载 Elasticsearch 的最新版本

  • 下载完成后,将下载文件的 sha1 值和下载时官网页面提供的 sha1 值进行对比,避免下载过程中被恶意攻击者拦截破坏文件,甚至注入恶意代码
  • 不要随便安装第三方的插件,插件有可能引入安全漏洞甚至本身自带后门,需谨慎使用
  • 关注 Elastic 网站,及时更新 Elasticsearch 至最新版本。Elasticsearch 每次版本发布都会优化和改进一部分功能,尤其是安全漏洞的补丁。同时,仔细阅读 Elasticsearch 的版本更新记录

注意:更新升级前,建议先进行快照备份,及本地测试

2. 网络访问控制

Elasticsearch 默认端口是 9200

  1. 不要把 Elasticsearch 的 9200 端口服务发布到互联网上
  2. 使用 云安全组防火墙 或本地操作系统防火墙对访问源 IP 进行隔离控制

3. 绑定访问源 IP

进入 config 目录,修改 elasticsearch.yml配置文件中以下参数:

network.bind_host: 192.168.0.1 # 设置绑定的 IP 地址,可以是 IPv4 或 IPv6 地址,默认为 0.0.0.0

network.publish_host: 192.168.0.1 # 设置其它节点和该节点交互的 IP 地址,如果不设置它会自动判断,值必须是个真实的 IP 地址

network.host: 192.168.0.1 # 同时设置上述两个参数:bind_host 和 publish_host。

4. 修改默认端口

进入 config 目录,修改 elasticsearch.yml 配置文件中以下参数:

ransport.tcp.port: 9300 # 设置节点间交互的 TCP 端口,默认是 9300。
transport.tcp.compress: true # 设置是否压缩 TCP 传输时的数据,默认为 false,即不压缩。
http.port: 9200 # 设置对外服务的 HTTP 端口,默认为 9200。

5. 关闭 HTTP 访问

进入 config 目录,修改 elasticsearch.yml 配置文件中以下参数:

http.enabled: false #是否使用 HTTP 协议对外提供服务,默认为 true,即开启

6. 使用 Shield 安全插件

Shield 是 Elastic 公司为 Elasticsearch 开发的一个安全插件。在安装此插件后,Shield 会拦截所有对 Elasticsearch 的请求,并进行认证与加密,保障 Elasticsearch 及相关系统的安全性。Shield 是商业插件,需要 Elasticsearch 的商业许可。第一次安装许可的时候,会提供 30 天的免费试用权限。30 天后,Shield 将会屏蔽 clusterhealth, cluster stats, index stats 等 API,其余功能不受影响

1. 用户认证

使用 Shield 可以定义一系列已知的用户,并用其认证用户请求。这些用户存在于抽象的“域”中。一个“域”可以是下面几种类型:

  • LDAP 服务
  • ActiveDirectory 服务
  • 本地 esusers 配置文件(类似 /etc/passwd)

2. 权限控制

Shield 的权限控制包含下面几种元素:

1)被保护的资源 SecuredResource:权限所应用到的对象,比如某个 index,cluster 等。
2)特权 Priviliege:角色对对象可以执行的一种或多种操作,比如 read,write 等。还可以是 indicies:/data/read/perlocate 等对某种对象特有的操作。
3)许可 Permissions:对被保护的资源拥有的一个或多个特权,如 read on the"products" index。
4)角色 Role:一组许可的集成,具有独立的名称。
5)用户 Users:用户实体,可以被赋予多种角色,他们可以对被保护的资源执行相应角色所拥有的各种特权

3. 安装 Shield

执行安装步骤前,请确保满足以下安装环境条件:

  • 安装了 Java7 或更新版本
  • 您将 Elasticsearch 1.5.0+ 解压安装到了本机上。如果您使用 APT 或 YUM 安装,默认的安装目录可能在 /usr/share/elasticsearch

参照以下步骤完成安装:

1)进入 Elasticsearch 安装目录:

cd /usr/share/elasticsearch

2)安装 Elasticsearch 许可插件:

bin/plugin -i elasticsearch/license/latest

3)安装 Shield 插件:

bin/plugin -i elasticsearch/shield/latest

4)将 Shield 配置文件移动或链接至 /etc/elasticsearch/shield 目录中:

ln -s /usr/share/elasticsearch/config/shield /etc/elasticsearch/shield

说明:Elasticsearch 服务在启动时会在 /etc/elasticsearch/shield 目录下寻找 Shield 配置文件,而这些配置文件在安装 Shield 时会出现在 /usr/share/elasticsearch/config/shield 中,因此需要将配置文件移动或链接至该目录

5)重启 Elasticsearch 服务:

service elasticsearch restart

6)新建一个 Elasticsearch 管理员账户,填写新密码:

bin/shield/esusers
useradd es_admin -r admin

7)直接使用 RESTFUL API 访问 Elasticsearch 的请求都会被拒绝:

curl -XGET 'http://localhost:9200/'

需要在请求中添加用户名和密码:

curl -u es_admin -XGET 'http://localhost:9200/'

refer:

7. 修改默认集群名称

Elasticsearch 默认的集群名称是 elasticsearch,请在您的生产环境中将其修改成其他名称。确保在不同的环境和不同的集群下使用不同的名称;并且在监控集群节点时,如果有未知节点加入,一定要及时预警。

8. 不要以 root 身份运行

不要以 root 身份来运行 Elasticsearch,不要和其他服务共用相同的用户,并把用户的权限最小化

应用示例:

sudo -u es-user ES_JAVA_OPTS="-Xms1024m -Xmx1024m"
/opt/elasticsearch/bin/elasticsearc

9. 正确设置数据目录

请确保为 Elasticsearch 的目录分配了合理的读写权限,避免使用共享文件系统。确保只有 Elasticsearch 的启动用户才有权访问目录。日志目录也需要正确配置,避免泄露敏感信息。

10. 定期进行备份

使用 Elasticsearch 提供的备份还原机制,定期对 Elasticsearch 的数据进行快照备份。

11. 禁用批量删除索引

Elasticsearch 支持使用全部(_all)和通配符(*)来批量删除索引。在生产环境,该操作存在一定风险,你可以通过设置 action.destructive_requires_name: true 参数来禁用它。

12. 启用日志记录功能

Elasticsearch 的 config 文件夹里面有两个配置文件:

  • elasticsearch.yml:基本配置文件。
  • logging.yml:日志配置文件。由于 Elasticsearch 使用 log4j 来记录日志的,logging.yml 中的设置请按普通 log4j 配置文件进行设置。

启用日志功能需要修改 elasticsearch.yml 配置文件:

path.logs: /path/to/logs # 设置日志文件的存储路径,默认是 Elasticsearch 根目录下的 logs 文件夹

0x09 Memcached 服务安全加固

漏洞描述

Memcached是一套常用的key-value缓存系统,由于它本身没有权限控制模块,所以对公网开放的Memcached服务很容易被攻击者扫描发现,攻击者通过命令交互可直接读取Memcached中的敏感信息

修复方案

Memcached默认没有启用安全功能,建议用户在使用时进行安全加固

1. 定期升级

使用官方最新版本Memcached

2. 配置访问控制

建议用户不要将服务发布到互联网上而被黑客利用,可以通过ECS安全组规则或iptables配置访问控制规则。例如,在Linux环境中运行命令iptables -A INPUT -p tcp -s 192.168.0.2 —dport 11211 -j ACCEPT,在iptables中添加此规则只允许192.168.0.2这个IP对11211端口进行访问

3. 绑定监听IP

如果Memcached没有在公网开放的必要,可在Memcached启动时指定绑定的IP地址为 127.0.0.1。例如,在Linux环境中运行以下命令:

memcached -d -m 1024 -u memcached -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pid

4. 使用最小化权限账号

使用普通权限账号运行,指定Memcached用户。例如,在Linux环境中运行以下命令来运行Memcached:

memcached -d -m 1024 -u memcached -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pid

5. 启用认证功能

Memcached本身没有做验证访问模块,Memcached从1.4.3版本开始,能支持SASL认证。SASL认证详细配置手册

6. 修改默认端口

修改默认11211监听端口为11222端口。在Linux环境中运行以下命令:

memcached -d -m 1024 -u memcached -l 127.0.0.1 -p 11222 -c 1024 -P /tmp/memcached.pid

Memcached命令参数说明

-d 是指启动一个守护进程。
-m 是指分配给Memcached使用的内存数量,单位是MB,以上为1024MB。
-u 是指运行Memcached的用户,推荐使用单独普通权限用户Memcached,而不要使用root权限账户。
-l 是指监听的服务器IP地址,例如指定服务器的IP地址为127.0.0.1。
-p 是用来设置Memcached的监听端口,默认端口为11211。建议设置1024以上的端口。
-c 是指最大运行的并发连接数,默认是1024。可按照您服务器的负载量来设定。
-P 是指设置保存Memcached的pid文件,例如保存在 /tmp/memcached.pid 位置。

7. 备份数据

为避免数丢失,升级前请做好备份,或者建立ECS硬盘快照

8. 主机基线检查

主机检测及防护: 使用HIDS自动检测不安全的配置项;Memcached漏洞的检测和防护

0x0A Docker服务安全加固

1. 加固主机操作系统

在部署前需要对服务器操作系统进行安全加固,例如,更新所有软件补丁、配置强密码、关闭不必要的服务端口等。

2. 使用强制访问控制策略

启用强制访问控制(Mandatory Access Control (MAC)),根据业务场景的具体分析,对Docker中使用的各种资源设置访问控制。

启用AppAamor功能:

启用SElinux功能:

3. 配置网络访问控制策略

根据实际应用,对需要外网访问的端口(例如管理界面、API 2375端口等重要端口)、需要与外网交互的网络地址、端口、协议等进行梳理,使用iptables或ECS安全组策略对网络的出入设置严格的访问控制。

4. 不要使用root用户运行

在软件使用中,有一些必须由root用户才能够进行的操作。但从安全角度,您需要将这一部分操作与仅使用普通用户权限即可执行的操作分离解耦。

在编写dockerfile时,您可以使用类似如下的命令创建一个普通权限用户,并设置创建的UID为以后运行程序的用户:

Docker命令参考:

5. 禁止使用特权

默认情况下,Docker容器是没有特权的,一个容器不允许访问任何设备;但当使用--privileged选项时,则该容器将能访问所有设备。

例如,当打开--privileged选项后,您就可以对Host中/dev/下的所有设备进行操作。但如果不是必须对host上的所有设备进行访问的话,您可以使用--device仅添加需要操作的设备。

6. 控制Docker容器资源配额

控制CPU份额

  • Docker提供-cpu-shares参数,用于在创建容器时指定容器所使用的CPU份额值

使用示例: 当使用命令docker run -tid -cpu-shares 100 ubuntu:stress创建容器时,则最终生成的cgroup的CPU份额配置可以下面的文件中找到。

cpu-shares的值不能保证可以获得1个vcpu或者多少GHz的CPU资源,仅仅只是一个弹性的加权值

  • Docker提供了-cpu-period-cpu-quota两个参数,用来控制容器可以分配到的CPU时钟周期。
    -cpu-period用来指定容器对CPU的使用要在多长时间内做一次重新分配,而-cpu-quota是用来指定在这个周期内,最多可以有多少时间用来运行这个容器。与-cpu-shares不同的是,这种配置是指定一个绝对值,而且没有弹性在里面,容器对CPU资源的使用绝对不会超过配置的值。
    cpu-periodcpu-quota的单位为微秒(μs)。cpu-period的最小值为1000微秒,最大值为1秒(10^6 μs),默认值为0.1秒(100000 μs)。cpu-quota的值默认为-1,表示不做控制。
    举例说明,如果容器进程需要每1秒使用单个CPU的0.2秒时间,可以将cpu-period设置为1000000(即1秒),cpu-quota设置为200000(0.2秒)。当然,在多核情况下,如果允许容器进程需要完全占用两个CPU,则可以将cpu-period设置为100000(即0.1秒),cpu-quota设置为200000(0.2秒)。
    使用示例:使用如下命令来创建容器docker run -tid -cpu-period 100000 -cpu-quota 200000 ubuntu

控制CPU内核

对于多核CPU的服务器,使用-cpuset-cpus-cpuset-mems参数,可以限定容器运行使用哪些CPU内核和内存节点。

该功能可以对需要高性能计算的容器进行性能最优的配置,对具有NUMA拓扑(具有多CPU、多内存节点)的服务器尤其有用。而如果服务器只有一个内存节点,则-cpuset-mems的配置基本上不会有明显效果。

使用示例:使用命令docker run -tid -name cpu1 -cpuset-cpus 0-2 ubuntu,表示创建的容器只能用0、1、2这三个内核。

混合使用CPU配额控制参数

在上述参数中,cpu-shares控制只用在容器竞争同一个内核的时间片时。如果通过cpuset-cpus指定容器A使用内核0,容器B只使用内核1,则在主机上只有这两个容器使用对应内核的情况,它们各自占用全部的内核资源,cpu-shares没有明显效果。

cpu-periodcpu-quota这两个参数一般联合使用。在单核或者通过cpuset-cpus强制容器使用一个CPU内核的情况下,即使cpu-quota超过cpu-period,也不会使容器使用更多的CPU资源。

cpuset-cpuscpuset-mems只对多核、多内存节点上的服务器有效,并且必须与实际的物理配置匹配,否则也无法达到资源控制的目的。

控制内存配额

和CPU控制一样,Docker也提供了若干参数来控制容器的内存使用配额,可以控制容器的swap大小、可用内存大小等。主要有以下参数:

  • memory-swappiness:控制进程将物理内存交换到swap分区的倾向,默认系数为60。系数越小,就越倾向于使用物理内存。取值范围为0-100。当值为100时,表示尽量使用swap分区;当值为0时,表示禁用容器swap功能。这点不同于宿主机,宿主机swappiness设置为0时,也不会禁用swap。
  • -kernel-memory:内核内存,不会被交换到swap上。一般情况下,不建议修改,可以直接参考Docker的官方文档。
  • -memory:设置容器使用的最大内存上限。默认单位为byte,可以使用K、G、M等带单位的字符串。
  • -memory-reservation:启用弹性的内存共享。当宿主机资源充足时,允许容器尽量多地使用内存,当检测到内存竞争或者低内存时,强制将容器的内存降低到memory-reservation所指定的内存大小。不设置此选项时,有可能出现某些容器长时间占用大量内存,带来性能上的损失。
  • -memory-swap:等于内存和swap分区大小的总和。设置为-1时,表示swap分区的大小是无限的。默认单位为byte,可以使用K、G、M等带单位的字符串。如果-memory-swap的设置值小于-memory的值,则使用默认值,为-memory-swap值的两倍。

7. 不运行不可信的Docker镜像

不要运行不可信的Docker镜像作为互联网服务器,避免运行不完全理解的Docker镜像作为互联网服务器。

8. 开启日志记录功能

Docker的日志可以分成两类,一类是stdout标准输出,另一类是文件日志。Dockerd支持的日志级别有debug、info、warn、error、fatal,默认的日志级别为info。

必要的情况下,您需要设置日志级别,这可以通过配置文件,或者启动参数-l--log-level来完成。

方法一:修改配置文件/etc/docker/daemon.json

方法二:使用docker run的时候指定

`--log-driver=syslog --log-opt syslog-facility=daemon`

9. 定期安全扫描和更新补丁

在生产环境中使用漏洞扫描工具可以检测镜像中的已知漏洞。

  • 容器通常都不是从头开始构建的,所以一定要进行安全扫描,以便及时发现基础镜像中任何可能存在的漏洞,并及时更新补丁。
  • 在应用程序交付生命周期中加入漏洞扫描的安全质量控制,防止部署易受攻击的容器。

0x0B Kubernetes服务安全加固

1. 确保镜像无安全漏洞

在部署前,应该确保所有的操作系统软件、Kubernetes软件为官方最新版本,防止部署后因为漏洞造成入侵事件。

在运维过程中,要不断执行持续安全漏洞扫描(Continuous Security Vulnerability Scanning),因为容器中可能存在包含已知漏洞(CVE)的过时包。新的漏洞每天都会出现,所以这不是一个一次性的工作,对镜像进行持续的安全评估是至关重要的。

定期对环境进行安全更新,一旦发现运行中容器的漏洞,您应该及时更新镜像并重新部署容器。尽量避免直接更新(例如,apt-update)到正在运行的容器,因为这样打破了镜像与容器的对应关系。

使用Kubernetes滚动升级功能可以方便地升级容器,该功能允许将镜像升级到最新版本来逐步更新正在运行的容器。

2. 只使用授权镜像

如果无法保证只运行符合组织策略的镜像,那么组织会面临运行脆弱甚至恶意容器的危险。从未知的来源下载和运行镜像是危险的,它相当于在生产服务器上运行未知服务商的软件。

使用私有镜像存储您的合法镜像,这样能大量减少可能进入到您的环境的镜像数量。建议您将安全评估(如漏洞扫描)加入持续集成(CI)中,使其成为构建流程的一部分。

持续集成应确保只使用审查通过的代码来构建镜像。当镜像构建成功后,要对它进行安全漏洞扫描,且只有在不存在问题时,才能将镜像推送到私有镜像仓库。在安全评估中失败的镜像不应该被推送到镜像仓库中。

Kubernetes镜像授权插件的工作已经完成,预计会随Kubernetes 1.4发布。该插件允许阻止未授权镜像的分发,单击查看详情

3. 限制对K8S节点的直接访问

应该限制SSH登录或SSH Key免登录Kubernetes节点,减少对主机资源未授权的访问。应该要求用户使用kubectl exec命令,此命令能够在不访问主机的情况下直接访问容器环境。

您可以使用Kubernetes授权插件来进一步控制用户对资源的访问。它允许设置对指定命名空间、容器和操作的细粒度访问控制规则。

4. 修改默认端口

Kubernets API Server进程提供Kuvernetes API。通常情况下,有一个进程运行在单一kubernetes-master节点上。

默认情况,Kubernetes API Server提供HTTP的两个端口:

本地主机端口

  • HTTP服务默认端口8080,修改标识-insecure-port
  • 默认IP是本地主机,修改标识—insecure-bind-address
  • 在HTTP中没有认证和授权检查
  • 主机访问受保护

安全端口

  • 默认端口6443,修改标识—secure-port
  • 默认IP是首个非本地主机的网络接口,修改标识—bind-address HTTPS服务。
  • 设置证书和密钥的标识,-tls-cert-file-tls-private-key-file
  • 认证方式,令牌文件或者客户端证书
  • 使用基于策略的授权方式

基于安全考虑,会移除只读端口,使用Service Account代替。

5. API管理端口访问控制

在某些配置文件中有一个代理(nginx)作为API Server进程运行在同一台机器上。该代理是HTTPS服务,认证端口是443,访问API Server是本地主机8080端口。在这些配置文件里,Secure Port通常设置为6443。

您可以使用ECS安全组防火墙规则,限制外部HTTPS通过443端口访问。

以上都是默认配置,每个云提供商可能会有所不同,您可以根据不同的业务场景灵活配置和调整。

6. 创建资源间的管理界限

限制用户权限的范围可以减少错误或恶意活动的影响。Kubernetes命名空间允许将资源划分为逻辑命名组。在一个命名空间中创建的资源对其他命名空间是隐藏的。

默认情况下,用户在Kubernetes集群中创建的每个资源运行在名称为“default”的默认空间内。您也可以创建额外的命名空间并附加资源和用户给它们。您可以使用Kubernetes授权插件来创建策略,以便将不同用户的访问请求隔离到不同的命名空间中。

例如:以下策略将允许”alice”从命名空间”fronto”读取pods。

7. 定义资源配额

运行没有资源限制的容器会将您的系统置于DoS或被其他租户干扰的风险中。为了防止和最小化这些风险,您应该定义资源配额。

默认情况下,Kubernetes集群中的所有资源没有对CPU和内存的使用限制。您可以创建资源配额策略,并附加到Kubernetes命名空间中来限制Pod对CPU和内存的使用。

下面的例子将限制命名空间中Pod的数量为4个,CPU使用在1和2之间,内存使用在1GB 和2GB之间。

compute-resources.yaml文件中:

10. API Server认证与授权

API Server权限控制分为三种:Authentication(身份认证)、Authorization(授权)、AdmissionControl(准入控制)。

身份认证

当客户端向Kubernetes非只读端口发起API请求时,Kubernetes通过三种方式来认证用户的合法性(即验证用户是否有权限操作API):证书认证,Token认证,基本信息认证。

  • 证书认证
    设置APIServer的启动参数:--client_ca_file=SOMEFILE
    验证被引用的文件中包含的client证书。如果被验证通过,那么这个验证记录中的主体对象将会作为请求的username。
  • Token认证
    设置APIServer的启动参数:--token_auth_file=SOMEFILE
    Token file的格式包含三列:token,username,userid。当使用Token作为验证方式时,需要在对APIServer的HTTP请求中增加一个Header字段Authorization,并将它的值设置为Bearer SOMETOKEN
  • 基本信息认证
    设置APIServer的启动参数:--basic_auth_file=SOMEFILE
    如果更改了文件中的密码,只有重新启动APIServer使其重新生效。该文件的基本格式包含三列:passwork,username,userid。当使用此作为认证方式时,需要在对APIServer的HTTP请求中增加一个Header字段Authorization,并将它的值设置为Basic BASE64ENCODEDUSER:PASSWORD

授权

在Kubernetes中,认证和授权是分开的,而且授权发生在认证完成之后。认证过程是检验发起API请求的用户是不是他所声称的那个人;而授权过程则判断此用户是否有执行该API请求的权限;因此授权是以认证的结果作为基础的。

Kubernetes授权模块应用于所有对APIServer的HTTP访问请求,而访问只读端口不需要认证和授权过程。APIServer启动时默认将authorization_mode设置为AlwaysAllow模式,即永远允许。

Kubernetes授权模块检查每个HTTP请求,并提取请求上下文中的所需属性(例如:user,resource kind,namespace)与访问控制规则进行比较。任何一个API请求在被处理前都需要通过一个或多个访问控制规则的验证。

目前,Kubernetes支持并实现了以下授权模式(authorization_mode),这些授权模式可以通过在APIServer启动时传入参数进行选择。

AlwaysDeny模式屏蔽所有的请求(一般用于测试)。AlwaysAllow模式允许所有请求,默认APIServer启动时采用的便是AlwaysAllow模式。ABAC(Attribute-Based Access Control,即基于属性的访问控制)模式则允许用户自定义授权访问控制规则。

ABAC模式

一个API请求中有4个属性被用于用户授权过程:

  • UserName:String类型,用于标识发起请求的用户。如果不进行认证、授权操作,则该字符串为空。
  • ReadOnly:Bool类型,标识该请求是否仅进行只读操作(GET就是只读操作)。
  • Kind:String类型,用于标识要访问的Kubernetes资源对象的类型。当访问/api/v1beta1/pods等API endpoint时,Kind属性才非空,但访问其他endpoint时,例如/version/healthz等,Kind属性为空。
  • Namespace:String类型,用于标识要访问的Kubernetes资源对象所在的namespace。

对于ABAC模式,在APIServer启动时除了需要传入--authorization_mode=ABAC选项外,还需要指定--authorization_policy_file=SOME_FILENAMEauthorization_policy_file文件的每一行都是一个JSON对象,该JSON对象是一个没有嵌套的Map数据结构,代表一个访问控制规则对象。一个访问控制规则对象是一个包含以下字段的Map:

  • user:--token_auth_file指定的user字符串。
  • readonly:true或false。true表明该规则只应用于GET请求。
  • kind:Kubernetes内置资源对象类型,例如pods、events等。
  • namespace:也可以缩写成ns。

一个简单的访问控制规则文件如下所示,每一行定义一条规则:

说明:缺省的字段与该字段类型的零值(空字符串,0,false等)等价。

一个授权过程就是一个比较API请求中各属性与访问控制规则文件中对应的各字段是否匹配的一个过程。当APIServer接收到一个API请求时,该请求的各属性就已经确定了,如果有一个属性未被设置,则APIServer将其设为该类型的空值(空字符串,0,false等)。匹配规则如下所示:

  • 如果API请求中的某个属性为空值,则规定该属性与访问控制规则文件中对应的字段匹配。
  • 如果访问控制规则的某个字段为空值,则规定该字段与API请求的对应属性匹配。
  • 如果API请求中的属性值非空且访问控制规则的某个字段值也非空,则将这两个值进行比较,如果相同则匹配,反之则不匹配。
  • API请求的属性元组(tuple)会与访问控制规则文件中的所有规则逐条匹配,只要有一条匹配则表示匹配成功,如若不然,则授权失败。

11. 记录所有的日志

Kubernetes提供基于集群的日志,允许将容器活动日志记录到一个日志中心。当集群被创建时,每个容器的标准输出和标准错误都可以通过运行在每个节点上的Fluentd 服务记录到Stackdriver或Elasticsearch中,然后使用Kibana进行查看

0xFF 参考资源