linux防火墙ufw以及iptables

1,直到服务器被攻击了,才知道防火墙的重要性

问题不大,被攻击了也就是cpu被别人跑满,账号密码被换掉而已。。。所以防火墙还是比较重要的,尤其是公网ip的防火墙

2,ufw

这个是ubuntu入门级别的防火墙了,使用方法比较简单,ubuntu系统自带,

常用指令:

sudo apt-get install ufw    #安装ufw
sudo ufw status numbered    #查看防火墙过滤规则
sudo ufw enable/disable    #激活防火墙,开机时自动启动/不启动
sudo ufw delete 3    #删除防火墙的规则
sudo ufw logging low    #启用防火墙的日志功能,默认的记录日志等级是low
sudo ufw allow from 49.72.93.80
sudo ufw default allow/allow|deny|reject incoming|outgoing    #设置默认允许服务器向外访问。
sudo ufw limit in 21116    #限制21115端口的接入访问    限制访问次数6次/30s

log文件在/var/log/ufw.log中,

log等级说明如下:
*low 记录与默认策略冲突的封装数据包(记录速度被限制)。记录与规则符合的数据包(没有要求关闭记录的)
*medium 记录与默认策略冲突的数据包(包括被规则允许的)、无效数据包、所有新连接。记录速度被限制。
*high 同medium,只是没有记录速度限制。附加记录所有数据包(有记录速度限制)。
*full 与high等同,只是取消记录限制。
日志文件位置:/var/log/ufw.log,日志文件内容解析:
[UFW BLOCK]:这是记录事件的描述开始的位置。在此例中,它表示阻止了连接。
IN:如果它包含一个值,那么代表该事件是传入事件
OUT:如果它包含一个值,那么代表事件是传出事件
MAC:目的地和源 MAC 地址的组合
SRC:包源的 IP
DST:包目的地的 IP
LEN:数据包长度
TTL:数据包 TTL,或称为 time to live。 在找到目的地之前,它将在路由器之间跳跃,直到它过期。
PROTO:数据包的协议
SPT:包的源端口
DPT:包的目标端口
WINDOW:发送方可以接收的数据包的大小
SYN URGP:指示是否需要三次握手。 0 表示不需要。

总体而言,简单可读性高,但是,并不算很容易配置,比如,我想限制21110端口的访问速率,改为每秒一次,那我就去改/etc/ufw/user.rule,改了也reload过了,发现根本改不动,得,咱还是换个工具吧。

3.iptables

这是存在于ubuntu内核中的程序,也是厉害了,这么说可能也不是很确切,防火墙是存在于linux内核中的程序,你要改防火墙规则,可以使用iptables或者是nft,我不知道他们具体关系是啥,但是一个比一个更底层,一个比一个更难理解。

说回来iptables是一个管着机器端口的程序,不光是外来访问,本地端口如3306也在它掌控范围,不仅能决定数据包是否能通过,还可以转发和修改数据包的内容,更有甚的icmp(能否ping通),v4还是v6通讯,网卡,docker容器类的虚拟端口等,全能管得到,它还知道你当前连接状态,限制流量等,也是内容非常非常庞杂了,主要参考的教程如下:感谢这位作者,要调试它首先要知道它的工作原理:

它有四张表:

• filter:这里面的链条,规则,可以决定一个数据包是否可以到达目标进程端口
• mangle: 这里面的链条,规则,可以修改数据包的内容,比如ttl
• nat:这里面的链条,规则,可以修改源和目标的ip地址,从而进行包路由。
• raw:这里面的链条,规则,能基于数据包的状态进行规则设定

每个表里都有一些内容,比如,filter表中,有如下规则:规则1,来自某个IP的包,直接拒绝。规则2,你要想访问我的80端口,直接拒绝,,,把规则1和2串联起来,就是一条链,当有一个包到了这张表的时候,它就会按照链的顺序进行匹配,如果规则1 不通过,就直接返回拒绝包的消息,这个包就不会往下走了。如果一直走完没有被拒绝,那就继续走其他的表。如果一直没有被拒绝,那这个包会最终到达它的目的地,返回的结果再经由路由判断一遍,就能完成一次收发了。当然了,实际情况更复杂一些。

细节咱也不多说,就从应用的角度出发,我上哪里去写一个规则,限制某个端口的数据访问,省得别人暴力破解我的密码。

如果你和我一样,要限制别人对本机的访问,大家一半都在filter表中chain:INPUT中做事情。所以话不多说,我们先看看filter中的内容。由于ufw我这边的filter类似这样:

Chain INPUT (policy DROP 25714 packets, 1351K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     103M  114G ufw-before-logging-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
2     103M  114G ufw-before-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
3    5179K  360M ufw-after-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
4    5179K  360M ufw-after-logging-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
5    5179K  360M ufw-reject-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
6    5179K  360M ufw-track-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0
2        0     0 DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0
3        0     0 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
4        0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
5        0     0 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0
6        0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0
7        0     0 ufw-before-logging-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
8        0     0 ufw-before-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
9        0     0 ufw-after-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
10       0     0 ufw-after-logging-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
11       0     0 ufw-reject-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
12       0     0 ufw-track-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1      94M  106G ufw-before-logging-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
2      94M  106G ufw-before-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
3     164K   13M ufw-after-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
4     164K   13M ufw-after-logging-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
5     164K   13M ufw-reject-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
6     164K   13M ufw-track-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0

除了以上内容,还有一堆ufw建立的chain,首先清理一下:

sudo iptables -t filter  -nvL --line    #指定查看filter表中的所有链和规则
sudo iptables -t filter --line -nvL limit-reject    #指定查看filter表中的limit-reject链中的规则

 

sudo iptables -t filter -D INPUT 1    #删除filter表中input链的第一条规则
sudo iptables -t filter -X  ufw-reject-input    #删除filter表中一个叫 ufw-reject-input的链,默认的链以及有引用的链不要乱删啊!

我基本把ufw的内容全删了,docker的暂时不动。

接下来定制自己的规则,规则主要包含两部分:条件 以及 动作

条件类似于:来自某个ip的包,指向某个IP的包,指向某个端口的包,等等

动作较简单,规定好的几类如下:

• ACCEPT: 直接接受该数据包,不会再走其他链条和规则。比如filter中的input表中的某个规则命中后,动作是ACCEPT,那么该数据包将被直接送达目标进程端口。
• DROP: 直接抛弃该数据包,并且没有任何返回。且不会再走其他链和规则
• REJECT: 跟DROP类似,但好歹还是会跟请求方返回一些拒绝信息,比如我们拒绝掉ICMP协议后,ping该主机,会返回“destination host unreachable”
• RETURN: 当前规则不做任何处理,返回。让给下一个规则处理
• LOG : 同RETURN类似,但只是会将请求信息记录到系统日志中,记录路径
还要补充一个,动作也可以指向一个自定义的chain,这样做的好处是,chain对规则进行了分组,可读性高而且方便管理

我的需求是,限制某些端口的访问频率,防止别人对我的暴力破解。这是我编辑的内容:

iptables -t filter -I INPUT -i lo -j ACCEPT    #首先在filter表的默认的INPUT链中接受所有的本地环回包,这个通常是自己访问自己,问题不大。
sudo iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT    #filter表的默认的INPUT链(默认的了哈,后面不说了)把已经建立的连接和由此相关的连接都接受。-I的意思是insert,就是在链前面插入规则,-A的意思是append在链后面插入规则。
iptables -t filter -N limit-reject    #在filter表中新增一个链 limit-reject ,这个链主要用处是限速以及速度太快的时候去拒绝访问的,顺带写了一下log

sudo iptables -t filter -I limit-reject -p tcp  -m multiport --dport  22,3000,21110,21116,21117  -m limit --limit 30/minute --limit-burst 10 -j ACCEPT    #编辑filter表,limit-reject链,新增一个限制规则,是,限制对22,3000,21110,21116,21117端口的访问,访问达到10次以后,就每2秒限制一次,原则上因为前面已经有一句已经建立的连接都接受的规则了,这里走到这里的应该都是新的连接请求,符合条件就accept,不符合继续往下走

sudo iptables  -t filter -A limit-reject -p tcp -m multiport --dport 22,3000,21110,21116,21117 -m limit --limit 3/minute --limit-burst 10 -j LOG
#某些端口有访问没有接受的话,记到系统log中去,位置:/var/log/syslog

sudo iptables  -t filter -A limit-reject -p tcp -j DROP
#但凡是走到这一句tcp的包,都扔了吧
sudo iptables  -t filter -A limit-reject -p udp -j DROP
#凡是走到这里的udp包,也扔了吧

咱就是说,也不能光设置不测试吧,这边还有对发的测试代码,

tcp的服务端:

def start_tcp_server(host='58.240.185.246', port=21110):
    # 创建socket对象
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # 设置选项,允许重新使用地址,这在重启服务时避免等待
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 绑定到地址和端口
        s.bind((host, port))
        # 开始监听
        s.listen()
        print(f"服务器启动成功,正在监听 {host}:{port}")

        while 1:
            # 接受客户端连接
            conn, addr = s.accept()
            clitdata = conn.recv(1024)
            # 发送数据给客户端
            print(f"连接地址: {addr}内容{clitdata}")
            conn.sendall(b'1djdhdgw')  # 发送数字1,以字节形式
            time.sleep(0.1)
            # 关闭连接
            conn.close()

# 启动服务
start_tcp_server()

其实普通http服务也将就能用,问题不大

python -m http.server 21110

tcp的客户端

import socket
import time

def send_tcp_data(ip, port, message):
    # 创建一个socket对象
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        try:
            # 连接到服务器
            s.connect((ip, port))
            print(f"已连接到 {ip}:{port}")

            # 将消息转换为字节发送
            s.sendall(message.encode("utf-8"))

            # 接收服务器响应
            response = s.recv(1)
            print(f"收到的响应: {response.decode()}")

        except socket.error as e:
            print(f"发送数据失败: {e}")

# 使用示例
server_ip = '58.240.185.246'  # 服务器的IP地址
#server_ip = 'localhost'  # 服务器的IP地址
server_port = 21110       # 服务器的端口号
send_message = 'SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.7\r\n'  # 要发送的消息

for i in range(50):
    print(i)
    send_tcp_data(server_ip, server_port, send_message)
    time.sleep(0.1)

我这边都对发验证过了。,不管限速还是drop还是写log都是管用的。

然后,就是如何持久化了,

写到这里才想起来,除了ipv4,还有ipv6呢,得,再来一次

首先把ufw中残留的设置给删了

sudo ip6tables -t filter-F    #默认表中的数据清除一下
sudo up6tables -t filter -X    #非默认的链都删了

然后ip6的访问都禁了:

 sudo ip6tables  -t filter -A INPUT -j REJECT

然后装个辅助包固定配置:

sudo apt install iptables-persistent
sudo iptables-save > /etc/iptables/rules.v4 //如果添加了ipv4 规则,执行这步
sudo ip6tables-save > /etc/iptables/rules.v6 //如果添加了ipv6规则,执行这步

遇到个问题是ip6tables提示没有权限,对,,sudo也没有权限,不过问题不大,直接cp替换掉文件就行了

sudo systemctl stop netfilter-persistent
sudo ip6tables-save > temp.log
sudo cp temp.log /etc/iptables
sudo mv temp.log rules.v6

ok

 

posted @ 2024-08-22 17:43  0点0度  阅读(321)  评论(0编辑  收藏  举报