Linux的Firewalld防火墙

使用防火墙可以对外部的数据包进行过滤和阻止,尽可能减少暴露在网络上的危险以保护系统安全。在RHEL7系的Linux系统中,已经将iptables防火墙管理工具使用firewalld代替。这篇文章的所有案例在RHEL8上成功执行。

1. firewalld防火墙简介

firewalld提供了一个动态管理的防火墙,在对防火墙规则修改时不需要断开连接就可以激活规则,并且支持网络区域zones,用来分配一个网络及相关连接一种程度上的信任。它已经对IPv4IPv6进行支持。并且可以选择对规则临时或永久修改。

本文使用的firewalld版本:0.7.0

1.1. firewalldiptables的主要区别

  • iptables/etc/sysconfig/iptables-config文件中存储配置。firewalld/etc/firewalld/下存储XML配置文件。

  • 使用iptables时每一个规则的更改意味着要清除所有旧的规则,然后从/etc/sysconfig/iptables-config配置文件中读取所有新的规则并载入。然而使用firewalld可以临时的将新添加的规则载入使用,不会像iptables一样丢失连接。

使用iptables命令行和firewalld工具和内核的NetFilter(内核防火墙框架)的交互示意图如下。

可以看出NetFilter才是真正的“防火墙”,它是Linux操作系统核心层内部的一个数据包处理框架,由图可以看出,不论是iptables命令行工具还是firewalld工具,它们都会通过iptables commandNetFilter(内核防火墙框架)放出来的接口实现沟通并使防火墙的规则生效。

1.2. 对firewalldZone网络区的理解

基于对网络中的设备和通信所给予的信任程度不同,firewalld防火墙可以用来将网络分割成不同的区域。

使用firewall-cmd --get-zones查看默认提供的zone,这些zone提供了一些基本的规则,也可以修改并保存规则。比如在工作单位时我切换到homeZone来屏蔽大多数让我分心的网络连接,然而回家后我需要娱乐娱乐,此时我将Zone改为home或者我信任我家里的网络并且改为了trustZone,这样又可以悠闲的享受那些娱乐网站咯。

Zone类型 说明
block 封锁 任何的连接都会被拒绝接收,并返回icmp(6)-host-prohibited拒绝信息
dmz 非军事区 处于此区域的设备可以公开访问,可以有限制的进入内部网络,仅接收经过选择的连接
drop 抛弃 接收到的任何连接都会被悄无声息的抛弃掉,不返回任何相应,仅允许对外发出的连接
external 外部 不信任来自网络的所有连接,仅接收经过选择的连接
home 家庭区 用于家庭网络。信任网络中的大多数连接,仅接收经过选择的连接
internal 内部 与home提供的默认规则相同
public 公共 不能相信网络内的其他计算机不会对您的计算机造成危害,仅接收经过选择的连接
trust 信任 可以接受任何的网络连接
work 工作 与public提供的默认规则相同

上面的所有Zones每个网络接口可以使用一个Zone作为当前Zone。当接入网络连接后,NetWorkManager将被分配为你设定好的默认Zone网络区,firewalld默认的网络区为public

2. 安装firewalld防火墙

安装firewalld需要以root用户身份执行下面的命令,并且执行firewalld命令时也要使用root用户身份执行。

dnf install firewalld

如果你安装了系统图形界面,并且也想使用图形化工具来管理firewalld,请执行如下命令。

dnf install firewall-config

但是本文中不会涉及到使用图形化工具配置firewalld防火墙

2.1. 启动防火墙

设置firewalld防火墙为默认防火墙并随着系统启动服务

systemctl enable firewalld

启动防火墙

systemctl start firewalld

如果对systemctl命令不了解,可以在浏览守护进程和控制服务相关博文。

2.2. 检查防火墙是否运行

systemctl status firewalld.service

systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-02-05 08:03:45 CST; 10h ago
     Docs: man:firewalld(1)
 Main PID: 1539 (firewalld)
    Tasks: 2 (limit: 49252)
   Memory: 35.7M
   CGroup: /system.slice/firewalld.service
           └─1539 /usr/libexec/platform-python -s /usr/sbin/firewalld --nofork --nopid

Feb 05 08:03:44 centos8 systemd[1]: Starting firewalld - dynamic firewall daemon...
Feb 05 08:03:45 centos8 systemd[1]: Started firewalld - dynamic firewall daemon.

使用firewall-cmd --state也可以查看防火墙运行状态

firewall-cmd --state
running # 运行中

3. 使用firewall-cmd进行管理

3.1. Zone网络区管理

3.1.1. 查看所有Zone网络区

firewall-cmd --list-all-zones

列出所有Zone的配置规则

firewall-cmd --list-all-zones
block
  target: %%REJECT%%
  icmp-block-inversion: no
  interfaces:
  sources:
...

还可以精简的只输出Zone的名字

firewall-cmd --get-zones

3.1.2. 查看firewalld默认Zone

firewall-cmd --get-default-zone

firewall-cmd --get-default-zone
public  # `firewalld`默认Zone为public

3.1.3. 查询某个网络接口上使用的Zone

firewall-cmd --get-zone-of-interface=XXXX

firewall-cmd --get-zone-of-interface=ens32  # 这里查看ens32网络接口当前的Zone
public  # 当前ens32接口上激活的是`public`Zone

3.1.4. 查看已激活的Zone的网络接口列表

firewall-cmd --get-active-zones

firewall-cmd --get-active-zones       
public  
  interfaces: ens32

# 可以看到,当前只有public网络区被激活。并且只有一个网络接口`ens32`使用这个Zone

3.1.5. 查询某一个Zone的详细规则信息

firewall-cmd --zone=public --list-all

firewall-cmd --zone=public --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens32
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 8096/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

  # 可以看到public网络区的规则信息:绑定了`ens32`网络接口,放行了cockpit dhcpv6-client ssh 服务的默认端口规则,还放行了8096的tcp端口。

3.1.6. 修改当前默认的Zone网络区

比如设置默认网络区为public,更改会立即生效。此时此刻,所有接口上默认绑定的Zone网络区都会切换到新的这个publicZone网络区上。

firewall-cmd --set-default-zone=public

3.1.7. 修改网络接口上的Zone网络区

如果有许多网络接口,要更改当前ens32网络接口绑定的Zone网络区为home,可以执行如下命令。

firewall-cmd --zone=home --change-interface=ens32

3.1.8. 删除绑定在网络接口上的Zone网络区

如果你不想让某以网络接口绑定到任何的网络区上,你可以执行如下命令。但是这么做无异于裸奔在网络世界中!

firewall-cmd --remove-interface=ens32

firewall-cmd --remove-interface=ens32
You're performing an operation over default zone ('public')
but your connections/interfaces are in zone 'trusted' (see --get-active-zones)
You most likely need to use --zone=trusted option.  # 由于没有加上--zone参数,这里给我们一个提示。

success

实际上任何一个网络接口都要绑定一个Zone网络区,如果将绑定的网络区删除,在reloadfirewall规则后会发现刚刚删除Zone的网络接口自动绑定到了trusted的Zone网络区,也就是说不受到防火墙的任何规则限制,比较危险。

3.2. 重新加载firewalld防火墙

3.2.1. 不中断用户连接

通常在对规则添加--permanent永久生效的选项后,规则不会立即生效,需要重新加载防火墙后配置的永久规则才会生效。在不中断用户现有的连接的情况下,建议使用firewall-cmd --reload来重新加载防火墙。

firewall-cmd --reload

3.2.2. 完全重载防火墙,并断开现有的用户连接

通常在firewalld防火墙出现问题时才会使用这种方式重载防火墙,这种方式会断开现有的网络连接,即丢失状态信息!

firewall-cmd --complete-reload

3.3. 打开/关闭防火墙端口(放行端口)

如果本地需要开放一个端口供外部访问,那么你可以将这个端口添加到某一网络区的放行端口规则中。

3.3.1. 打开防火墙端口(放行端口)

firewall-cmd --add-port=portid[-portid]/protocol [--permanent] [--zone=zone]

参数(portid[-portid]):要开放的端口号,如果是一个范围则使用10000-12000表达一个范围。

参数(protocol):TCP/UDP协议

可选参数(zone):将规则添加到哪个Zone网络区中,如果缺省该参数则添加到默认Zone网络区中。

可选选项(–permanent):规则永久保存,重新加载防火墙后生效。如果缺省该参数则修改的规则立即生效,但是重新加载防火墙后规则会失效

firewall-cmd --add-port=6000-7000/tcp --permanent --zone=public # 在public网络区下放行6000~7000之间TCP通信协议的网络端口(闭区间),规则永久保存并且在下一次重新加载防火墙后生效。
success

firewall-cmd --zone=public --list-all # 检查修改后的public网络区的规则,发现并没有新添加的放行端口规则,说明规则还没有生效,需要重新加在防火墙。
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens32
  sources:
  services: cockpit dhcpv6-client http https ssh
  ports: 8096/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:


firewall-cmd --reload # 重新加载防火墙

firewall-cmd --list-all --zone=public # 再次检查规则是否生效。发现规则已生效。
public
  target: default
  icmp-block-inversion: no
  interfaces:
  sources:
  services: cockpit dhcpv6-client http https ssh
  ports: 8096/tcp 6000-7000/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

下面在默认的网络区内永久放行单个TCP端口

firewall-cmd --add-port=6000/tcp --permanent # 这里没有添加`--zone`的选项和参数,会自动添加到默认网络区中。

firewall-cmd --reload 重新加载防火墙,使规则生效。

3.3.2. 关闭防火墙端口(关闭端口)

刚刚已经将端口放行,并且暴露在外。如果需要这个端口的服务不再使用,出于安全考虑你可以将这个端口从放行规则中删除掉。

firewall-cmd --remove-port=portid[-portid]/protocol [--permanent] [--zone=zone]

参数(–remove-port=portid[-portid]/protocol):你要移除的端口号/端口范围,注意表明是TCP协议还是UDP协议哦。和你添加的时候一样,如果添加时你写的是一个端口范围,那么删除时只能将全部的端口范围删除掉,不能只删除端口范围中一部分端口。

可选参数(–zone=zone):关闭指定网络区中的端口,如果缺省该参数,则从默认的网络区中删除端口。

可选选项(–permanent):规则永久保存,重新加载防火墙后生效。如果缺省该参数则修改的规则立即生效,但是重新加载防火墙后规则会失效

firewall-cmd --remove-port=8080/tcp --permanent #关闭默认Zone网络区开放的TCP8080端口

firewall-cmd --remove-port=1000-2000/udp --zone=public --permanent  #永久关闭在public网络区下开放的UDP1000-2000端口。

3.4. 放行/关闭防火墙某一服务(放行服务)

firewalld中存储了常见服务的默认端口信息,如果你的服务没有更改过默认的端口号,那么可以直接使用firewald放行服务,它会根据默认规则,自动放行一个或一组此服务需要的端口。只需要管理员来记忆服务名就好咯!

3.4.1. 查看所有支持的服务

firewall-cmd --get-services

你能看到所有firewald存储的默认服务端口号,如果此时你需要开启某一服务的端口就不需要记他们默认的端口号了,试试firewall-cmd --add-service=XXXX

3.4.2. 查询服务端口详细信息

刚才查询到了所有支持的服务,那firewalld给我们提供的默认服务的端口号究竟是啥呢?

firewall-cmd --permanent --service=https --get-port

返回443/tcp

3.4.3. 放行服务端口

firewall-cmd --add-service=service [--permanent] [--zone=zone] [--timeout=timeval]

参数(–add-service):要放行的服务名,如ssh、http、https。

可选参数(–zone=zone):将此规则添加到网络区,如果缺省该参数,添加到默认网络区内。

可选参数(–timeout=timeval):临时生效时间,不可与--permanent连用。表达方式可以是--timeout=[100s | 100m | 100h]。(timeval is either a number (of seconds) or number followed by one of characters s(seconds), m(minutes), h(hours))

可选选项(–permanent):规则永久保存,重新加载防火墙后生效。如果缺省该参数则修改的规则立即生效,但是重新加载防火墙后规则会失效

firewall-cmd --add-service=https --permanent  #永久放行在默认网络区内的https(443端口)服务

firewall-cmd --add-service=https --timeout=1h #临时放行在默认网络区内的https服务1小时

firewwall-cmd --add-service=https --zone=home --permanent #永久放行在home网络区中的https服务

3.4.4. 关闭服务端口

如果关闭某一服务所对应的端口,那么将会时该服务无法对外部提供服务,请确定好删除的服务名,以免影响业务的正常服务!

你可以通过firewall-cmd --list-all查看默认网络区下,当前开放了哪些服务与规则,确保在关闭之前,这些服务和端口是开放的状态。

firewall-cmd --remove-service=https [--permanent] [--zone=zone]

参数与规则与关闭端口类似,在此不再赘述。

3.5. 端口转发

端口转发可以将到达某一端口的数据包转发到本机或其他机器上另一个的一个端口上。使用端口转发功能需要现开启firewalld的IP伪装功能。

使用firewall-cmd --list-forward-ports可以查询所有端口转发规则。

3.5.1. 开启IP伪装

防火墙可以实现IP伪装,默认为关闭状态。可以使用firewall-cmd --query-masquerade进行查询。

firewall-cmd --query-masquerade查询默认Zone网络区内的ip伪装功能是否开启。

返回no则为关闭状态。

firewall-cmd --add-masquerade [--permanent] [--zone=zone] [--timeout=timeval]

参数(–add-masquerade):开放IP转发功能。

可选参数(–zone=zone):将此规则添加到网络区,如果缺省该参数,添加到默认网络区内。

可选参数(–timeout=timeval):临时生效时间,不可与--permanent连用。表达方式可以是--timeout=[100s | 100m | 100h]

可选选项(–permanent):规则永久保存,重新加载防火墙后生效。如果缺省该参数则修改的规则立即生效,但是重新加载防火墙后规则会失效

如果不需要IP地址伪装,使用下面的命令关闭。

firewall-cmd --remove-masquerade [--permanent] [--zone=zone]

3.5.2. 开启端口转发

请确保在开启端口转发前已经开启IP伪装功能。如果需要IPv6的端口转发,请富规则方式配置。

firewall-cmd --add-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]] [--permanent] [--zone=zone] [--timeout=timeval]

参数(–add-forward-port):

portid:本机端口号
protocal:UDP/TCP协议,此处只能选择一个。
[portid]:要转发到的端口。如果缺省该参数则默认与设置的本地端口一致。
[address]:要转发到的地址。如果缺省该参数则默认为本机地址。

可选选项(–permanent):规则永久保存,重新加载防火墙后生效。如果缺省该参数则修改的规则立即生效,但是重新加载防火墙后规则会失效

其他参数不再赘述。

下面是一些使用端口转发的案例:

firewall-cmd --add-masquerade # 开启IP伪装(转发到其他IP上时必须开启,仅转发本地端口则非必须开启)


firewall-cmd --add-forward-port=port=8888:proto=udp:toport=53 --permanent #永久将本机默认网络区下的本地UDP8888端口转发到本地UDP53端口上。

firewall-cmd --add-forward-port=port=7777:proto=tcp:toport=6667:toaddr=192.168.1.160 --zone=public  #临时在public网络区下将本机7777端口的TCP流量转发到192.168.1.160上的6667端口上,重载防火墙后失效

firewall-cmd --add-forward-port=port=7777:proto=tcp:toport=6667:toaddr=192.168.1.160 --timeout=100s #临时在100秒内将默认网络区下将本机7777端口的TCP流量转发到192.168.1.160上的6667端口上,超时或重载防火墙后失效。

3.5.3. 关闭端口转发

使用 firewall-cmd --list-forward-ports查询当前已加载所有的端口转发规则

firewall-cmd --list-forward-ports #查询当前已加载所有的端口转发规则
port=8888:proto=udp:toport=53:toaddr= #发现有一个转发规则

当不需要这个规则时我们可以删除它。

firewall-cmd --remove-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]] [--permanent] [--zone=zone] [--timeout=timeval]

参数部分不再解释。与添加时的意思相对应。可以先查询规则,确定好你要删除的规则后将规则填写到--remove-forward-port=后即可。

注意:如果你添加端口转发规则时,选择了--permanet永久生效,那么在永久删除时也要添加上--permanet选项。除非是想临时取消此这条规则。

firewall-cmd --list-forward-ports #查询当前已加载所有的端口转发规则
port=8888:proto=udp:toport=53:toaddr= #发现有一个转发规则,现在删除此规则。

firewall-cmd --remove-forward-port=port=8888:proto=udp:toport=53:toaddr=  --permanet  # 在默认的网络区内永久删除这条转发规则。

firewall-cmd --reload #使修改生效

4. 使用富规则配置复杂firewalld策略

通过rich language语法,可以建立复杂防火墙规则。并且还可以永久生效。这种语言使用关键词值,是 iptables 工具的抽象表示。

4.1. 富规则的命令格式

firewall-cmd --add-rich-rule='rule' [--permanent] [--zone=zone]  [--timeout=timeval]

# rule规则详细参数
rule [family="<rule family>"]
[ source address="<address>" [invert="True"] ]
[ destination address="<address>" [invert="True"] ]
[ <element> ]
[ log [prefix="<prefix text>"] [level="<log level>"] [limit
value="rate/duration"] ] [ audit ]
[ accept|reject|drop ]

一条富规则绑定在一个Zone网络区下,一个网络区可以绑定多条富规则。如果几个规则相互影响或者冲突,则匹配第一条规则。

4.2. 理解多规则命令

4.2.1. family

[family="<rule family>"]

family rule可以是IPv4或者IPv6,将对选择的流量进行限制。此处的参数可以省略不填写,但是source或者destination中出现了IP地址,则必须填写并指定rule。省略则同时对IPv6和IPv4进行限制。

4.2.2. source

[ source [not] address="<address>" ]

源地址,不支持主机名。源地址可以是一个IPv4地址或IPv6地址或者一个网络地址段。可以使用not写在地址前来反转你的地址所表达的限定范围。

4.2.3. destination

[ destination [not] address="<address>" ]

限制目标地址,与源地址使用相同的表示方法,同样支持not反转。

4.2.4. element

element为限定的规则。该项只能为下面的几个要素之一,不能将他们同时进行应用。根据你的需求选取一个要素进行限制。

4.2.4.1. service服务名称

此处填写firewalld默认提供的服务名称。获取firewalld默认提供的服务清单可以使用此命令firewall-cmd --get-services,也可以看上面的3.4章节了解firewalld内置服务。

service name="server"

4.2.4.2. port端口

port port=number_or_range protocol="tcp | udp"

number_or_range端口既可以是一个端口号,也可以是一个端口范围,如6000-7111protocol协议可以指定为tcpudp

4.2.4.3. protocol协议

protocol value=protocol_name_or_ID

protocol_name_or_ID可以是一个协议名,也可以是协议ID,可以在/etc/protocols文件中查看预设支持的协议。

4.2.4.4. icmp-block阻断

icmp-block name=icmptype_name

icmptype_name为特定的icmp类型名,使用icmp-block元素可以禁止一个或多个ICMP类型。所有的ICMP类型可以使用firewall-cmd --get-icmptypes命令来查看。

4.2.4.5. icmp-type类型

此处可以为所选的icmp类型指定动作。

4.2.4.6. masquerade IP地址伪装

规则里的IP伪装。用源地址而不是目的地址来把伪装限制在一个范围内。

4.2.4.7 forward-port端口转发

forward-port port=number_or_range protocol=protocol to-port=number_or_range to-addr=address

number_or_range可以是一个端口号或者端口范围。protocolUDP/TCP协议。address目的IP地址。

firewall-cmd --add-forward-port语法相近。如果省略address,则为本地端口转发。

4.2.5. log日志

log [prefix=prefix text] [level=log level] limit value=rate/duration

记录访问请求。你可以指定日志记录等级,log level记录等级可以是 emerg,alert,crit,error,warning,notice,info 或者 debug 中的一个。

rate/duration,rate为次数,duration是持续时间,单位可以是s,m,h,d。最大限定值是 1/d ,意为每天最多有一条日志进入。

4.2.6. Action动作(accept|reject|drop)

使用accept所有新的连接请求都会被允许。使用reject连接将被拒绝,对方将会收到一个拒绝信息。使用drop所有数据包会被丢弃,并且不会返回任何消息给对方。

4.3. 删除富规则

删除富规则与删除端口转发类似,直接将添加富规则的语言规则填写到--remove-rich-rule选项里。首先应该查询目前所有生效的富规则。

4.3.1 查询所有富规则

firewall-cmd --list-rich-rules

之后会以一行行的形式返回每一条富规则。

4.3.2 删除富规则

firewall-cmd --remove-rich-rule='rule' [--permanent]

将查询到要删除的富规则复制到--remove-rich-rule=参数后面,以防止输入出错。如果想永久删除,那么您需要添加--permanent选项以永久保存。如果你在添加富规则时仅仅是临时生效,那么不应该填写此选项。

firewall-cmd --list-rich-rules  # 显示所有生效的富规则
rule icmp-type name="echo-request" drop # 返回一条富规则

firewall-cmd --remove-rich-rule='rule icmp-type name="echo-request" drop' --permanent # 永久删除该条富规则
success #返回结果

firewall-cmd --reload #重载防火墙规则后生效

4.4. 富规则配置实例

4.4.1 阻止echo-request请求

阻止ICMP协议中的echo-request也就是我们常说的禁止Ping。

firewall-cmd --add-rich-rule='rule icmp-type name="echo-request" drop' --permanent

使用Drop动作可以伪装成无法联系到主机的效果。

4.4.2 拒绝某一IP(段)访问本机ftp服务

firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" service name="ftp" reject' --permanent

永久拒绝IP来自10.0.1.*的客户访问本机FTP服务器。

firewall-cmd --add-rich-rule='rule family="ipv6" source address="2409:8a18:600:b250::239" service name="ssh" log limit value="1/m" drop' --permanent

永久拒绝来自2409:8a18:600:b250::239的用户远程登录到本机SSH服务器,并且以每分钟一次的速率进行日志记录。

4.4.3 使用富规则进行端口转发

永久对当IP来自为192.168.1.175用户访问本机22端口时,将流量转发至192.168.1.3的22号tcp端口上。注意需要开启IP地址伪装,重载防火墙规则后生效。

firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.175" forward-port port="22" protocol="tcp" to-addr="192.168.1.3"' --permanent

开启IP地址伪装,否则无法将流量转发到其他IP上。

firewall-cmd --add-masquerade --permanent

4.4.4 丢弃来自某IP域的所有连接

firewall-cmd --add-rich-rule='rule family="ipv4" source address="172.23.0.0/16" drop'

丢弃来自172.23.0.0/16网段下的所有连接。

基本内容基本已经完成,后续会继续更新细节。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇