使用 iptables 来防止 ss 服务器被用于发送垃圾邮件

梨子2016-11-8
本文最后更新于 2386 天前(2016-11-8),其中的信息可能已经有所发展或者不再适用于现阶段。
本文全长 2229 字,全部读完大约需要 7 分钟。

昨天,笔者像往常一样用 ss 上网时,发现代理服务器挂了。笔者随即打开了 vps 管理界面,发现了服务器被 VPS 服务商封号了,说是服务器向外发送了大量垃圾邮件,如图

1-768x350.png

然后笔者不假思索的点击了这个按钮

2-768x132.png

然后不到 2 分钟之后又被封了……gg 这次仔细研究了上面那张图里的信息,发现原因是服务器上运行的 ss mu,好在用户也不多,一查发现,有人在 Windows 客户端打开了“允许来自局域网的连接”,这样一来如果接入的是广域网,就会出现一大批来自各种 ip 的 1080 端口请求,这其中就不乏有发送垃圾邮件的。为了解决这些问题,决定在服务器上开启 iptables 防火墙。

将其中与邮件相关的端口整理如下

收:109 110 995(POP3)143(IMAP) 993(IMAP)
发:25 465 587

25端口(SMTP):25端口为SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)服务所开放的,是用于发送邮件。 如今绝大多数邮件服务器都使用该协议。当你给别人发送邮件时,你的机器的某个动态端口(大于1024)就会与邮件服务器的25号端口建立一个连接,你发送的邮件就会通过这个连接传送到邮件服务器上,保存起来。
109端口(POP2):109端口是为POP2(Post Office Protocol Version 2,邮局协议2)服务开放的,是用于接收邮件的。
110端口(POP3):110端口是为POP3(Post Office Protocol Version 3,邮局协议3)服务开放的,是用于接收邮件的。
143端口(IMAP):143端口是为IMAP(INTERNET MESSAGE ACCESS PROTOCOL)服务开放的,是用于接收邮件的。

下面简单介绍 iptables 的配置,

一、配置 iptables,我们先写一个配置文件,例如笔者写的是

vim /etc/iptables.banmailports.rules
*filter
-A OUTPUT -p tcp --dport 21 -j LOG --log-prefix "IPTABLES TCP-OUT 21:"
-A OUTPUT -p tcp --dport 21 -j DROP
-A OUTPUT -p tcp --dport 22 -j LOG --log-prefix "IPTABLES TCP-OUT 22:"
-A OUTPUT -p tcp --dport 22 -j DROP
-A OUTPUT -p tcp --dport 23 -j LOG --log-prefix "IPTABLES TCP-OUT 23:"
-A OUTPUT -p tcp --dport 23 -j DROP
-A OUTPUT -p tcp --dport 25 -j LOG --log-prefix "IPTABLES TCP-OUT 25:"
-A OUTPUT -p tcp --dport 25 -j DROP
-A OUTPUT -p tcp --dport 109 -j LOG --log-prefix "IPTABLES TCP-OUT 109:"
-A OUTPUT -p tcp --dport 109 -j DROP
-A OUTPUT -p tcp --dport 110 -j LOG --log-prefix "IPTABLES TCP-OUT 110:"
-A OUTPUT -p tcp --dport 110 -j DROP
-A OUTPUT -p tcp --dport 143 -j LOG --log-prefix "IPTABLES TCP-OUT 143:"
-A OUTPUT -p tcp --dport 143 -j DROP
-A OUTPUT -p tcp --dport 465 -j LOG --log-prefix "IPTABLES TCP-OUT 465:"
-A OUTPUT -p tcp --dport 465 -j DROP
-A OUTPUT -p tcp --dport 587 -j LOG --log-prefix "IPTABLES TCP-OUT 587:"
-A OUTPUT -p tcp --dport 587 -j DROP
-A OUTPUT -p tcp --dport 993 -j LOG --log-prefix "IPTABLES TCP-OUT 993:"
-A OUTPUT -p tcp --dport 993 -j DROP
-A OUTPUT -p tcp --dport 995 -j LOG --log-prefix "IPTABLES TCP-OUT 995:"
-A OUTPUT -p tcp --dport 995 -j DROP
-A OUTPUT -p tcp --dport 995 -j LOG --log-prefix "IPTABLES TCP-OUT 995:"
-A OUTPUT -p tcp --dport 995 -j DROP
COMMIT

首先先来解释一下 INPUT, OUTPUT,dport 和 sport 的意思:

dport:目的端口
sport:来源端口
初学 iptables 比较容易迷糊,但是我尽量用通俗的语言给你讲解。
dport 和 sport 字面意思来说很好理解,一个是数据要到达的目的端口,一个是数据来源的端口。
但是在使用的时候要分具体情况来对待,这个具体情况就是你的数据包的流动行为方式。(INPUT还是OUTPUT)
比如你的例子:/sbin/iptables -A INPUT -p tcp –dport 80 -j ACCEPT
注意里面的 INPUT 参数,这个代表你的这条数据包的进行的 “进入” 操作!
那么你的这条数据包可以这么描述:

  1. 这是一条从外部进入内部本地服务器的数据。
  2. 数据包的目的(dport)地址是80,就是要访问我本地的80端口。
  3. 允许以上的数据行为通过。
    总和:允许外部数据访问我的本地服务器80端口。
    再看第 2 条例子:/sbin/iptables -A INPUT -p tcp –sport 80 -j ACCEPT
  4. 这是一条从外部进入内部本地服务器的数据。
  5. 数据包的来源端口是(sport)80,就是对方的数据包是80端口发送过来的。
  6. 允许以上数据行为。
    总结:允许外部的来自 80 端口的数据访问我的本地服务器。
    input 方式总结: dport 指本地,sport 指外部。
    如果你的数据包是(OUTPUT)行为,那么就是另外一种理解方式:
    比如:
    /sbin/iptables -A OUTPUT -p tcp –dport 80 -j ACCEPT
  7. 这是一条从内部出去的数据。
  8. 出去的目的(dport)端口是80。
  9. 允许以上数据行为。
    output 行为总结:dport 指外部,sport 指本地

那么这里的 OUTPUT 很好理解,就是禁止服务器向外的请求。那么为什么要用 dport 呢,这里有一段非常好的解释

For SMTP you don’t need any --sport rule. The source and destination don’t depend on direction – they’re match on the packet’s source and destination ports. Every connection will have a random source port, so there’s nothing to match on.

If I remove the first OUTPUT line then my server won’t receive emails & if I remove the last line it won’t send emails. This is wrong. Only the INPUT line matters for receiving emails. Also, only the OUTPUT --dport 25 line matters for sending emails. So these rules should be enough:

-A INPUT -p tcp --dport 25 -j ACCEPT
-A OUTPUT -p tcp --dport 25 -j ACCEPT

The problem may be that you set OUTPUT to default to DROP, but allowed established connection on INPUT only. Usually people leave OUTPUT defaulting to ACCEPT. If you want to continue using a whitelist for OUTPUT, you’ll have to add:

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Also, please read up on SMTP ports. Some of those you listed are only needed for email submissions and deprecated encryption, not for server-to-server communication. This may change how you plan your rules.

保存本文件,然后把本规则加载,使之生效,注意,iptables 不需要重启,加载一次规则就成了。

iptables-restore < /etc/iptables.banmailports.rules

然后再查看最新的配置,应该所有的设置都生效了:

iptables -L

二、保存生效的配置,让系统重启的时候自动加载有效配置

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

注意,如果当前用户不是root,即使使用了sudo,也会提示你没有权限,无法保存,所以执行本命令,你必须使用root用户. 可以使用sudo -i快速转到root,使用完成,请及时使用su username切换到普通帐户。

三、为了重启服务器后,规则自动加载,我们创建如下文件:

vim /etc/network/if-pre-up.d/iptables

内容如下:

#!/bin/bash
/sbin/iptables-restore < /etc/iptables.up.rules

最后,设置可执行仅限

chmod +x /etc/network/if-pre-up.d/iptables

这样做完以后,防火墙就可以滤掉这些端口的请求了。然而我们还想记录下它的日志,那么就需要另外的一些配置。简单地解释如下,

-A OUTPUT -p tcp --dport 25 -j LOG --log-prefix "IPTABLES TCP-OUT 25:"

这个就表示记录下了这条访问的日志,应该很好理解。

日志默认输出的位置,CentOS 是在 /var/log/messages,Debian/Ubuntu 是在 /var/log/kern.log,这里尤其要注意。笔者用的是 Debian,找了好久也没找到输出的日志,最后发现只要

apt-get install rsyslog

就好了。。坑

如果想要把 iptables 的日志单独输出到一个文件,给大家提供了一个很好的回答作参考

These logs are generated by the kernel, so they go to the file that receives kernel logs: /var/log/kern.log. If you want to redirect these logs to a different file, that can’t be done through iptables. It can be done in the configuration of the program that dispatches logs: rsyslog. In the iptables rule, add a prefix that isn’t used by any other kernel log:

iptables -A INPUT -s 192.168.11.0/24 -j LOG --log-prefix='[netfilter]'

Following the example set by 20-ufw.conf, create a file under /etc/rsyslog.d/my_iptables.conf containing

然后重新启动 rsyslog

systemctl restart rsyslog

就可以将日志输出到一个单独的文件啦

除特殊说明以外,本网站文章采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。