保护我们的VPS的步骤

本教程介绍了如何使用Debian GNU / Linux准备和保护虚拟专用服务器(VPS)。 在开始之前,先假设一些事情:

  1. 您对GNU / Linux具有中等的熟悉程度。
  2. 有一个供个人使用的VPS,我们可以通过SSH访问。
  3. VPS具有专用的外部ipv4 250.250.250.155,而我们的提供商拥有250.250.0.0/16块。 (1)
  4. 在我们的VPS中,我们将仅启用http,https和ssh服务以供从外部访问。
  5. 外部DNS不会启用,因为通常是在我们提供商的面板中完成的。 (2)
  6. 它将作为超级用户运行。

安装

首先,让我们更新服务器并安装一些我们需要的软件包:

#aptitude更新和aptitude安全升级#aptitude -RvW安装dropbear gesftpserver sslh iptables-永久ulogd fail2ban nginx-light apache2-utils dnsutils telnet ghostscript poppler-utils zip解压缩unrar-free p7zip-完全少了Multitail Tee mc

组态

现在,我们将创建一个工作用户。 以root用户身份在服务器上工作是不安全的,因此我们将首先创建一个特殊用户:

adduser运算符usermod -aG sudo运算符

第一个命令创建操作员用户,第二个命令将其添加到组中 须藤,这将允许您以root用户身份运行应用程序。

调整超级用户的权限

至于正常工作,我们将使用用户 操作者 先前创建的,我们需要以超级用户身份调整命令执行选项,为此我们执行以下命令:

维苏多

该命令基本上允许修改文件 / etc / sudoers; 其中应包含以下几行:

默认值env_reset,timestamp_timeout = 0%sudo ALL =(ALL:ALL)ALL

在第一行中,该选项已添加到默认值 时间戳超时 它使您可以设置执行sudo命令时密码的有效时间(以分钟为单位)。 默认值为5,但这有时是不安全的,原因有两个:

  1. 如果我们在密码过期之前无意中使计算机保持登录状态,则有人可以以超级用户身份执行命令而没有任何限制。
  2. 如果通过无知我们在密码过期之前执行了包含恶意代码的应用程序或脚本,则该应用程序可以未经我们明确同意而以超级用户身份访问我们的系统。

因此,为避免风险,我们将值设置为零,也就是说,每次执行sudo命令时,都必须输入密码。 如果将负值设置为-1,则结果是密码永不过期,这将产生与我们想要的相反的结果。

在第二行中,阐明了sudo组可以在任何计算机上执行任何命令,这是很常见的,尽管可以调整。 (3)为了方便起见,有些人将行放在下面以避免输入密码:

%sudo ALL =(全部:全部)NOPASSWD:全部

但是,正如我们之前解释的那样,这样做存在风险,因此不建议这样做。

禁用重启

出于安全原因,我们还将使用组合键禁用重启 按Ctrl + Alt + Del键,为此我们必须在文件中添加此行 / etc / inittab中:

ca:12345:ctrlaltdel:/ bin / echo“ Ctrl + Alt + Del已被禁用。”

用DropBear替换OpenSSH

大多数VPS都装有OpenSSH,这当然非常有用,但是除非我们需要利用OpenSSH的所有功能,否则VPS会有更轻巧的替代品,例如 落熊,通常足以正常使用。 但是,此应用程序的缺点是它没有集成的SFTP服务器,这就是为什么我们在一开始就安装该软件包的原因 gesftp服务器.

要配置Dropbear,我们将修改文件 / etc /默认/ dropbear 这样它包含以下两行:

NO_START = 0 DROPBEAR_EXTRA_ARGS =“-w -p 127.0.0.1:22 -I 1200 -m”

第一行仅启用服务,第二行执行几项操作:

  1. 避免root访问。
  2. 将服务放在本地接口的端口22上(稍后我们将解释原因)。
  3. 设置等待时间(20分钟)。

安全卫士

端口22(SSH)是众所周知的,通常是黑客尝试破坏的第一个端口,因此我们将改用端口443(SSL)。 碰巧该端口用于通过HTTPS进行安全浏览。

因此,我们将使用sslh软件包,它只是一个多路复用器,它分析到达端口443的数据包,并根据流量类型是SSH还是SSL在内部将它们路由到一个服务或另一个服务。

SSLH无法在已经在监听其他服务的接口上进行监听,这就是为什么我们之前让Dropbear在本地接口上进行监听的原因。

现在,我们需要做的是指示根据服务类型来确定接口和监听端口,以及重定向数据包的位置,为此,我们将修改配置文件 / etc /默认/ sslh:

DAEMON = / usr / sbin / sslh DAEMON_OPTS =“-user sslh --listen 250.250.250.155:443 --ssh 127.0.0.1:22 --ssl 127.0.0.1:443 --pidfile / var / run / sslh / sslh。 pid“ RUN =是

最后,我们重新启动服务:

服务ssh停止&&服务dropbear启动&&服务sslh重新启动

在执行上一个命令之后,我们的安全会话可能会被中断,在这种情况下,足以再次登录,但这一次是与工作用户并使用端口443。如果不中断该会话,建议将其关闭,然后从适当的值重新开始。

如果一切正常,我们可以继续以root身份工作,如果需要,请卸载OpenSSH:

sudo su-aptitude -r清除openssh-server

防火墙

我们要做的下一件事是将日志从防火墙中分离到单独的文件中 /var/log/firewall.log 为了便于进一步分析,这就是为什么我们在启动时安装了ulogd软件包。 为此,我们将编辑文件 /etc/logd.conf 调整相关部分:

[LOGEMU]文件=“ /var/log/firewall.log” sync = 1

接下来,我们将修改记录轮换文件 / etc / logrotate / ulogd 保持每天轮换(带有日期)并将压缩的齐射保存在目录中 / var / log / ulog /:

/var/log/ulog/*.log /var/log/firewall.log {每日dateext missingok压缩delaycompress共享脚本创建640个root adm后旋转/etc/init.d/ulogd重新加载mv /var/log/firewall.log-* .gz / var / log / ulog / endscript}

因此,我们将通过执行以下操作来创建netfilter规则:

IPT = $(iptables)IPEXT = 250.250.250.155 IPEXTBLK = 250.250.0.0 / 16 IPBCAST = 255.255.255.255 $ IPT -F $ IPT -X $ IPT -Z $ IPT -A INPUT -i lo -j ACCEPT $ IPT- P输入下降$ IPT -P向前下降$ IPT -P输出接受$ IPT -A输入-m状态-状态无效-j ULOG -ulog前缀IN_INVALID $ IPT -A输入-p igmp -j ULOG -ulog -前缀IN_IGMP $ IPT -A输入-m pkttype -pkt类型广播-j ULOG -ulog前缀IN_BCAST $ IPT -A INPUT -m pkttype -pkt类型多播-j ULOG -ulog前缀IN_MCAST $ IPT -A转发-j ULOG -ulog前缀FORWARD $ IPT -N ICMP_IN $ IPT -A输入!  -i lo -p icmp -j ICMP_IN $ IPT -A ICMP_IN -p icmp -f -j ULOG --ulog前缀IN_ICMP_FRAGMENTED $ IPT -A ICMP_IN -p icmp -m icmp -m长度!  --length 28:1322 -j ULOG --ulog前缀IN_ICMP_INVALIDSIZE $ IPT -A ICMP_IN -p icmp -m icmp -m hashlimit --hashlimit-above 4 / sec --hashlimit-mode srcip --hashlimit-srcmask 24- -hashlimit-name icmpflood -j ULOG --ulog-prefix IN_ICMP_FLOOD $ IPT -A ICMP_IN -p icmp -m icmp -m hashlimit -hashlimit-upto 64kb / min -hashlimit-mode srcip -hashlimit-srcmask 24-hashlimit -名称icmpattack -j ULOG --ulog前缀IN_ICMP_FLOOD $ IPT -A ICMP_IN -p icmp -m icmp -m u32!  --u32“ 0x4&0x3fff = 0x0” -j ULOG --ulog前缀IN_ICMP_ATTACK $ IPT -A ICMP_IN -p icmp -m icmp!  --icmp类型的echo请求-m状态-状态NEW -j ULOG --ulog前缀IN_ICMP_INVALID $ IPT -A ICMP_IN -p icmp -m icmp --icmp类型echo-r​​equest -j ULOG -ulog-前缀IN_ICMP $ IPT -A ICMP_IN -p icmp -m icmp -icmp类型echo-r​​equest -m limit --limit 1 / sec --limit-burst 4 -j ACCEPT $ IPT -A ICMP_IN -p icmp -m icmp --icmp类型echo-r​​eply -m限制--limit 2 /秒--limit-burst 4 -j ACCEPT $ IPT -A ICMP_IN -p icmp -m icmp --icmp类型目的地-不可访问-m限制-限制2 /秒-极限突发4 -j接受$ IPT -A ICMP_IN -p icmp -m icmp --icmp类型的时间超过-m极限-极限2 /秒-极限突发4 -j接受$ IPT -A ICMP_IN -p icmp -m icmp --icmp-type参数问题-m limit --limit 2 / sec --limit-burst 4 -j ACCEPT $ IPT -A ICMP_IN -j RETURN $ IPT -N UDP_IN $ IPT-输入!  -i lo -p udp -j UDP_IN $ IPT -A UDP_IN!  -我!  -p udp -f -j ULOG --ulog前缀IN_UDP_FRAGMENTED $ IPT -A UDP_IN -p udp -m udp --sport 53 -m长度!  --length 28:576 -j ULOG --ulog前缀IN_UDP_DNS_INVALIDSIZE $ IPT -A UDP_IN -p udp -m udp --dport 53 -m -state --state NEW -j ULOG --ulog前缀IN_UDP_DNSREQUEST $ IPT- UDP_IN -p udp -m udp --dport 53 -m -state --state NEW -j REJECT-拒绝icmp-port-unreachable $ IPT -A UDP_IN -p udp -m udp!  -体育53!  -s $ IPEXTBLK!  -d $ IPBCAST -m状态-状态NEW -j ULOG -ulog前缀IN_UDP $ IPT -A UDP_IN -p udp -m udp -m状态-state已建立,相关-j接受$ IPT -A UDP_IN -j返回$ IPT -N TCP_IN $ IPT -A INPUT!  -i lo -p tcp -j TCP_IN $ IPT -A TCP_IN!  -我!  -p tcp -f -j ULOG --ulog前缀IN_TCP_FRAGMENTED $ IPT -A TCP_IN -p tcp -m tcp --sport 53 -m状态--state已建立,相关-m长度!  --length 513:1500 -j ULOG --ulog前缀IN_TCP_DNS_INVALIDSIZE $ IPT -A TCP_IN -p tcp -m tcp --dport 53 -m状态-状态NEW -j ULOG --ulog-prefix IN_TCP_DNS $ IPT -A TCP_IN -p tcp -m tcp --dport 53 -m状态--state新-j拒绝-拒绝icmp-port-unreachable $ IPT -A TCP_IN -p tcp -m tcp -m多端口!  --dports 80,443 -m状态--state NEW -j ULOG --ulog-prefix IN_TCP $ IPT -A TCP_IN -p tcp -m tcp -m multiport --dports 80,443 -m state --state NEW -m hashlimit-hashlimit -upto 4 /秒--hashlimit-burst 16 --hashlimit-mode srcip --hashlimit-name navreq -j ACCEPT $ IPT -A TCP_IN -p tcp -m tcp -m multiport --dports 80,443 -m状态-状态已建立-m connlimit!  --connlimit-above 16 -j ACCEPT $ IPT -A TCP_IN -p tcp -m tcp -m多端口! 

使用先前的配置,我们的VPS应该得到合理的保护,但是如果我们希望可以对其进行更多保护,则可以使用一些更高级的规则。

并非所有的VPS都可以为netfilter安装额外的模块,但是非常有用的一个是 PSD,这可以避免端口扫描。 不幸的是,默认情况下该模块未集成到netfilter中,因此必须安装某些软件包然后构建该模块:

aptitude -RvW安装iptables-dev xtables-addons-source模块辅助模块-assistant --verbose --text-mode自动安装xtables-addons-source

完成上述操作后,我们可以添加如下规则:

iptables -A INPUT -m psd --psd-weight-threshold 15 -psd-delay-threshold 2000 -psd-lo-port-weight 3 -psd-hi-ports-weight 1 -j ULOG -ulog-前缀IN_PORTSCAN

上面的规则基本上意味着我们将创建一个计数器,该计数器将在每次尝试访问低于3的端口时增加1024,并在每次尝试访问高于1的端口时增加1023。计数器在不到15秒的时间内达到20,软件包将被注册 日志 作为尝试portscan。 仍然可以一次丢弃这些数据包,但是在这种情况下,我们打算使用 fail2ban,我们将在以后进行配置。

创建规则后,我们必须采取某些预防措施以使它们持久化,否则在重新启动服务器时我们将丢失它们。 有几种方法可以做到这一点。 在本教程中,我们将使用开始时安装的iptables-persistent软件包,该软件包将规则存储在 /etc/iptables/rules.v4 y /etc/iptables/rules.v6 对于ipv6。

iptables-save> /etc/iptables/rules.v4

实际上,尽管在古巴尚未广泛使用ipv6,但我们可以创建一些基本规则:

IPT = $(其中ip6tables)$ IPT -P输入下降$ IPT -P转发下降$ IPT -P输出接受$ IPT -A输入-i lo -j接受$ IPT -A输入! -i lo -m状态-状态已建立,相关-j接受未设置IPT

这些规则也可以持久化:

ip6tables-save> /etc/iptables/rules.v6

最后,为了提高安全性,我们清除了防火墙的注册表并重新启动服务:

echo -n> /var/log/firewall.log服务logrotate重新启动服务ulogd重新启动服务iptables-永久重新启动

Nginx的

我们将Nginx用作Web服务器,因为与真实服务器相比,VPS的RAM数量往往减少,因此通常比Apache更轻便。

在配置Nginx之前,我们将创建一个证书(无密码)以通过HTTPS使用:

cd / etc / nginx openssl genrsa -des3 -out cert.key 4096 cp -v cert.key cert.key.original openssl req -new -key cert.key -out cert.csr openssl rsa -in cert.key.original- outcert.key openssl x509 -req -days 365 -in cert.csr -signkey cert.key -out cert.crt

完成此操作后,我们将为用户“ elusuario”创建一个密码文件:

htpasswd -c .htpasswd用户

接下来,我们将修改文件 / etc / nginx /网站可用/默认 设置默认的网站首选项。 它可能看起来像这样:

服务器{server_name localhost; index index.html index.htm default.html default.htm; root / var / www; location / {#设置验证的顺序和要加载的页面,如果未找到URI try_files $ uri $ uri / /index.html; }}服务器{听127.0.0.1:443; server_name localhost; index index.html index.htm default.html default.htm; root / var / www; ssl on; ssl_certificate cert.crt; ssl_certificate_key cert.key; ssl_session_timeout 5m; #仅在TLS(比SSL更安全)上启用HTTPS ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #优先考虑高强度密码[HIGH],#将中等强度密码[MEDIUM]移到列表的末尾,#禁用低强度密码[LOW](40和56位)#禁用具有导出算法的密码[ EXP]#禁用空密码[eNULL],不进行身份验证[aNULL],SSL(版本2和3)和DSS(仅允许使用不超过1024位的密钥)ssl_ciphers HIGH:+ MEDIUM :! LOW :! EXP:!aNULL :! eNULL:!SSLv3:!SSLv2:!DSS; #优先使用服务器的加密方法(默认情况下使用客户端的加密方法)。 location / {#启用身份验证auth_basic“登录”; auth_basic_user_file /etc/nginx/.htpasswd; #如果未找到URI try_files $ uri $ uri / = 404,则设置验证顺序和要加载的页面代码; #允许为通过身份验证的用户自动创建索引; autoindex_exact_size关闭; autoindex_localtime on; }}

我们检查配置是否正确:

nginx -t

最后,我们重新启动服务:

服务nginx重启

Fail2Ban

在开始配置Fail2Ban之前,为了提高安全性,我们停止了服务并清理了注册表:

fail2ban-client停止echo -n> /var/log/fail2ban.log

接下来,我们创建配置文件 /etc/fail2ban/jail.local 具有以下自定义内容:

#自定义配置文件/etc/fail2ban/jail.local#[DEFAULT] findtime = 43200; 禁酒时间12小时= 86400; 1天maxretry = 3; 禁令将在第四次尝试后生效[ssh] enabled = false [nginx-auth] enabled = true筛选器= nginx-auth action = iptables-multiport [name = NoAuthFailures,port =“ http,https”] logpath = / var / log / nginx * / *错误* .log [nginx-badbots]已启用=真实过滤器= apache-badbots操作= iptables-multiport [名称= BadBots,端口=“ http,https”] logpath = / var / log / nginx * /*access*.log bantime = 4; 604800周maxretry = 1 [nginx登录]启用=真正的过滤器= nginx登录操作= iptables-multiport [名称= NoLoginFailures,端口=“ http,https”] logpath = / var / log / nginx * / *访问*。日志禁止时间= 0; 1800分钟[启用nginx-noscript] =真实操作= iptables-multiport [名称= NoScript,端口=“ http,https”]过滤器= nginx-noscript logpath = /var/log/nginx*/*access*.log maxretry = 30 [启用nginx-proxy] = true操作= iptables-multiport [名称= NoProxy,端口=“ http,https”]过滤器= nginx-proxy日志路径= /var/log/nginx*/*access*.log bantime = 0 ; 604800周maxretry = 1 [启用防火墙] = true操作= iptables-multiport [名称=防火墙]过滤器=防火墙日志路径= /var/log/firewall.log maxretry = 0

完成后,我们在目录中创建 /etc/fail2ban/filters.d/ 以下文件:

#/etc/fail2ban/filter.d/nginx-auth.conf#身份验证过滤器#阻止使用基本身份验证失败的IP#[定义] failregex =未提供用于基本身份验证的用户/密码。 用户*找不到*客户端: 用户*密码不匹配*客户端: ignoreregex =
#/etc/fail2ban/filter.d/nginx-login.conf#登录过滤器#阻止使用Web应用程序登录页面进行身份验证的IP#扫描HTTP 200 + POST /会话的访问日志=>登录失败#[定义] failregex = ^ -。* POST /会话HTTP / 1 \ ..“ 200 ignoreregex =
#/etc/fail2ban/filter.d/nginx-noscript.conf#Noscript过滤器#阻止试图执行脚本的IP,例如.php,.pl,.exe和其他有趣的脚本。 #匹配,例如#192.168.1.1--“ GET /something.php#[定义] failregex = ^ -。* GET。*(\。Php | \ .asp | \ .exe | \ .pl | \ .cgi | \ scgi)ignoreregex =
#/etc/fail2ban/filter.d/proxy.conf#代理过滤器#阻止试图将服务器用作代理的IP。 #匹配,例如#192.168.1.1--“获取http://www.something.com/#[定义] failregex = ^ -。* GET http。* Ignoreregex =
#/etc/fail2ban/filter.d/firewall.conf#防火墙过滤器#[定义] failregex = ^。* IN_(INVALID | PORTSCAN | UDP | TCP |)。* SRC = * $ ignoreregex =

最后,我们启动服务并加载配置:

fail2ban-service -b fail2ban-client重新加载

验证

最后,我们可以使用 尾巴 o 多尾–全部关注。 实际上,后一个应用程序具有以下优点:它允许您同时查看多个文件并提供基本的语法突出显示。

如果未在VPS中配置电子邮件帐户,建议禁用启动multitail时出现的警告消息,对此我们将执行以下命令:

echo“ check_mail:0”>〜/ .multitailrc

实际上,我们可以使用短命令(例如“ flog”)来创建别名(4)来快速查看日志:

别名flog ='multitail --follow-all /var/log/firewall.log /var/log/fail2ban.log'

1)这些是虚拟的价值。
2)一旦了解其他服务的工作原理,启用其他服务就很容易了。
3)有关更多详细信息,请运行man sudoers。
4)可以选择添加到〜/ .bash_aliases文件中


6条评论,留下您的评论

发表您的评论

您的电子邮件地址将不会被发表。 必填字段标有 *

*

*

  1. 负责数据:MiguelÁngelGatón
  2. 数据用途:控制垃圾邮件,注释管理。
  3. 合法性:您的同意
  4. 数据通讯:除非有法律义务,否则不会将数据传达给第三方。
  5. 数据存储:Occentus Networks(EU)托管的数据库
  6. 权利:您可以随时限制,恢复和删除您的信息。

  1.   MSX

    有一些有趣的事情,+ 1

  2.   友喜

    @Hugo这行在配置中:

    ssl_protocols SSLv3 TLSv1;

    我会从中删除SSLv3,因为该协议不再安全,即使在Debian Jessie中,由于该原因,许多服务都已配置为避免使用该协议。

    有关此主题的信息:

    https://www.linode.com/docs/security/security-patches/disabling-sslv3-for-poodle
    http://disablessl3.com/

    1.    雨果

      这个想法并不是真的通过HTTPS提供主要服务,而是说明如何在SSH上使用端口443,而又不会在必要时失去将其用于HTTPS的可能性,但是感谢您的警告。

      无论如何,我已经更新了该文章以对nginx配置进行一些修改,并附带一些注释,以便通过这种加密机制进一步阐明一些内容,并修复一些小错误。

  3.   丹尼尔·PZ

    非常感谢您的精彩教程,现在我将把它付诸实践! :D,坚持下去 DesdeLinux,他们总是让我惊讶,来自秘鲁的问候。

  4.   安德库拉

    非常感谢您的分享。

  5.   费尔南多

    很好的指南,从我开始撰写此博客开始,它就来自珍珠。现在,我将要安装我的第一个vps,甚至遇到很多问题,甚至更多,但是这篇文章使我摆脱了许多疑问,感谢和问候。