Debian服务器默认安装后,网络访问控制其实已经具备一定基础,但很多人忽略了从“谁能连进来”到“连进来能做什么”之间的完整链路。真正有效的安全权限管控,不是只配一个防火墙或者改一下SSH端口,而是要把网络层的访问限制、服务层的认证策略、文件系统层的权限约束串起来。下面直接讲具体怎么做。

先收紧SSH,这是最容易被扫描的入口

Debian服务器的SSH服务默认允许密码登录和root账户直接登录,这等于把大门敞开了让暴力破解工具试。第一步就是修改/etc/ssh/sshd_config,把PermitRootLogin改成no,把PasswordAuthentication改成no,只保留密钥登录。改完后执行systemctl restart sshd让配置生效。如果你需要从多个设备登录,提前把公钥加到/root/.ssh/authorized_keys或者对应用户的.ssh目录里,权限必须是600,目录权限700,否则sshd会拒绝读取。

还有一个细节:MaxAuthTries设置为3,LoginGraceTime设置为30秒,这样能有效拖慢自动化扫描工具的速度。如果你的服务器只对固定几个IP开放SSH,直接用防火墙限制来源IP,比任何Fail2Ban都彻底。

用nftables替代iptables做基础访问控制

Debian 10及之后的版本默认推荐nftables。nftables的语法比iptables清晰很多,而且规则合并后性能更好。一个基础的入站策略可以这样写:

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        # 允许回环
        iif lo accept
        # 允许已建立和相关的连接
        ct state established,related accept
        # 允许ICMPv4和ICMPv6的ping
        ip protocol icmp icmp type echo-request accept
        ip6 nexthdr icmpv6 icmpv6 type echo-request accept
        # 允许SSH,仅限特定来源IP
        tcp dport 22 ip saddr 203.0.113.0/24 accept
        # 允许Web服务
        tcp dport {80, 443} accept
    }
    chain forward {
        type filter hook forward priority 0; policy drop;
    }
    chain output {
        type filter hook output priority 0; policy accept;
    }
}

把上面的规则保存到/etc/nftables.conf,然后执行systemctl enable nftables && systemctl start nftables。注意policy drop意味着所有未明确允许的入站流量全部丢弃,包括你以后新加的服务端口。所以每次部署新服务时,记得同步更新nftables规则。

服务绑定地址要精确到接口

很多服务默认监听0.0.0.0,也就是所有网卡的所有IP。如果服务器有公网IP和内网IP,数据库、Redis、Memcached这类服务根本不需要暴露到公网。检查每个服务的配置文件,把bind参数改成内网IP或者127.0.0.1。比如Redis的redis.conf里设置bind 127.0.0.1 10.0.0.5,MySQL的my.cnf里设置bind-address = 10.0.0.5。改完后用ss -tlnp检查监听地址,确保没有服务意外监听在0.0.0.0上。

对于必须监听公网的服务,比如Nginx或Apache,也要在虚拟主机配置里限制访问路径。比如管理后台、状态页面、API调试接口,这些都不应该对全网开放。Nginx里可以用allow和deny指令限制/admin和/server-status这类路径的来源IP。

用systemd限制服务的网络访问能力

防火墙只能控制进出服务器的流量,但控制不了服务进程本身能访问哪些地址。如果某个服务被入侵,攻击者可以利用这个服务作为跳板去访问内网其他机器。systemd提供了IPAddressAllow和IPAddressDeny指令,可以直接限制服务能访问的IP范围。比如限制某个PHP-FPM进程只能访问本机的MySQL和Redis:

[Service]
IPAddressAllow=127.0.0.1
IPAddressAllow=10.0.0.0/8
IPAddressDeny=any

把这个配置加到对应服务的systemd unit文件里,然后执行systemctl daemon-reload和systemctl restart服务名。这样即使服务被攻破,攻击者也无法从这台服务器主动连接外网或者内网其他网段。这个功能依赖内核的cgroup v2和eBPF,Debian 11及更新版本默认支持。

内核参数加固网络栈

Debian默认的内核网络参数偏宽松,有几个参数值得调整。编辑/etc/sysctl.d/99-security.conf,加入以下内容:

# 忽略所有ICMP重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# 不发送ICMP重定向
net.ipv4.conf.all.send_redirects = 0
# 反向路径过滤,防止IP欺骗
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# 忽略所有源路由包
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
# 记录可疑包
net.ipv4.conf.all.log_martians = 1
# 限制TCP半连接数量,缓解SYN洪水
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_syncookies = 1

执行sysctl -p /etc/sysctl.d/99-security.conf立即生效。这些参数不会影响正常业务,但能挡住一部分网络层的探测和欺骗攻击。

利用TCP Wrappers做应用层访问控制

虽然TCP Wrappers在部分新软件中不再被支持,但Debian仓库里很多传统服务仍然会调用libwrap。检查/etc/hosts.allow和/etc/hosts.deny这两个文件。一个简单的策略是先在hosts.deny里写ALL: ALL,然后在hosts.allow里放行需要的服务。比如只允许特定IP访问SSH和vsftpd:

# /etc/hosts.allow
sshd: 203.0.113.0/24
vsftpd: 198.51.100.10
# /etc/hosts.deny
ALL: ALL

注意不是所有服务都支持TCP Wrappers,用ldd /usr/sbin/sshd | grep libwrap可以确认。如果输出里有libwrap.so,说明这个服务会读取hosts.allow和hosts.deny。

定期审计监听端口和已建立的连接

安全管控不是配置完就结束了,需要定期检查。用ss -tulnp查看所有监听端口,确认每个端口对应的服务都是你预期中的。用ss -tnp查看当前所有TCP连接,注意有没有异常的ESTABLISHED状态连接,特别是来自陌生IP的连接。如果发现可疑连接,先找到对应的进程,再决定是终止连接还是进一步排查。

另外可以用netstat -i查看网络接口的统计信息,关注RX-DRP和TX-DRP这两列。如果丢弃包数量持续增长,说明防火墙规则在拦截流量,需要确认是不是误伤了正常业务。

权限管控要落实到文件和目录

网络访问控制解决的是“谁能连进来”,但连进来之后能做什么,取决于文件系统权限。Debian默认的umask是022,新建文件权限是644,目录是755。对于Web应用的配置文件、数据库备份、私钥文件,这些权限太宽松了。检查/etc/ssh/目录下的私钥文件,权限必须是600,所有者必须是root。检查Web应用的.env、config.php、settings.py这类文件,权限改成640,所有者改成运行Web服务的用户,组改成该用户所在的组。

还有一个容易被忽略的地方:/tmp目录。很多服务会在/tmp下创建临时文件,如果/tmp权限是1777,任何用户都能在里面创建文件,但只有文件所有者能删除自己的文件。这个粘滞位是必要的,但要注意/tmp下是否有服务遗留的敏感文件。更安全的做法是给每个服务配置独立的临时目录,并在systemd unit里用PrivateTmp=true隔离。

用AppArmor限制服务的能力边界

Debian默认启用了AppArmor,但大部分服务的profile是未强制模式。检查/etc/apparmor.d/目录,看看有没有针对你正在运行服务的profile。比如Nginx、MySQL、PHP-FPM都有现成的profile模板。执行aa-status查看当前处于enforce模式的服务。如果某个服务没有profile,可以用aa-genprof生成一个基础profile,然后根据服务实际行为逐步调整。AppArmor能限制服务能访问的文件路径、能执行的程序、能使用的网络协议,这是比防火墙更细粒度的管控。

最后强调:最小权限原则贯穿始终

Debian服务器网络访问安全权限管控的核心就一句话:只给必要的权限,只开必要的端口,只允许必要的来源。每加一条防火墙规则、每改一个服务配置、每部署一个新应用,都要问自己:这个权限是不是必须的?这个端口是不是必须对全网开放?这个文件的读取权限是不是必须给所有用户?把这些问题想清楚,服务器的安全基线自然就建立起来了。不要追求一次配置永久安全,安全是一个持续审计和调整的过程。