Rocky Linux 9 从入门到精通008 — LDAP 账号管理(FreeIPA 部署篇)

FreeIPA 简介

在《Rocky Linux 9 从入门到精通 008 —— LDAP 账号管理(理论篇)》一文中,我们提到市场上有许多实现 LDAP 服务相关产品。本章节将以开源产品 FreeIPA 为例进行讲解。

官方简介:

FreeIPA 是一个信息安全管理集成解决方案,它结合了 Linux(基于 Fedora)、389 目录服务器、MIT Kerberos、NTP、DNS 以及 Dogtag 证书系统等多种组件。并且为用户提供了网页界面和命令行两种管理方式。
简单来说,FreeIPA 是专为 Linux/UNIX 网络环境设计的统一身份认证解决方案。通过 FreeIPA 服务器,管理员可以集中管理用户、用户组、主机等与网络安全相关的信息,实现统一的身份认证、授权以及账号管理。
FreeIPA 基于众所周知的开源组件和标准协议开发,特别注重管理的简便性以及安装、配置任务的自动化。
多个 FreeIPA 服务器可以轻松配置在同一个 FreeIPA 域中,以实现数据的冗余备份和系统的横向扩展。389 Directory Server 是 FreeIPA 的核心数据库,提供完整的多主 LDAPv3 目录服务。MIT Kerberos KDC 则负责实现单点登录(Single-Sign-on)功能。Dogtag 项目的集成证书颁发机构(CA)则进一步增强了认证能力。可选地,FreeIPA 还可借助内置的 ISC Bind 服务器来管理域名服务(DNS)。
关于访问控制、权限分配和其他网络管理任务,FreeIPA 允许管理员通过网页界面或 ipa 命令行工具进行集中管理,大大简化了日常运维的流程。

服务器资源规划

由于 FreeIPA 需要 DNS 服务器提供域名解析功能,因此本次我们将继续使用之前搭建的 CoreDNS 服务器来承担域名解析的任务。

节点资源规划:

主机名 IP 作用
CoreDNS-001 192.168.1.1 CoreDNS 服务器主节点
CoreDNS-002 192.168.1.2 CoreDNS 服务器从节点
ldap-001 192.168.1.3 LDAP 服务器主节点
ldap-002 192.168.1.4 LDAP 服务器从节点
Client-001 192.168.3.1 LDAP 客户端节点

 

DNS Zone 配置信息:

配置名称
Zone(本地区域) rockylinux.lan

 

CoreDNS Zone 配置参考:Rocky Linux 9 从入门到精通007– DNS管理(Zone 篇)
注意:添加以上主机名与 IP 的 A 记录解析。

FreeIPA 服务器部署

# 安装 FreeIPA
[root@ldap-001 ~]# dnf install -y ipa-server

# 初始化
[root@ldap-001 ~]# ipa-server-install
# 安装日志存放位置
The log file for this installation can be found in /var/log/ipaserver-install.log
==============================================================================
This program will set up the IPA Server.
Version 4.12.2
# 安装包含的组件,默认 * 星号都是要安装的
This includes:
  * Configure a stand-alone CA (dogtag) for certificate management
  * Configure the NTP client (chronyd)
  * Create and configure an instance of Directory Server
  * Create and configure a Kerberos Key Distribution Center (KDC)
  * Configure Apache (httpd)
  * Configure SID generation
  * Configure the KDC to enable PKINIT
# 按回车键,开始安装
To accept the default shown in brackets, press the Enter key.
# 是否配置集群的 bind DNS,因为木子使用的 CoreDNS,所以使用默认设置 no
Do you want to configure integrated DNS (BIND)? [no]: 

Enter the fully qualified domain name of the computer
on which you''re setting up server software. Using the form
<hostname>.<domainname>
Example: master.example.com

# 设置服务器主机名,采用默认设置
Server host name [ldap-001.rockylinux.lan]: 
The domain name has been determined based on the host name.

# 域名配置,使用 CoreDNS 上配置的 Zone
Please confirm the domain name [rockylinux.lan]: 

# kerberos 域名设置,采用默认的大写
The kerberos protocol requires a Realm name to be defined.
This is typically the domain name converted to uppercase.
Please provide a realm name [ROCKYLINUX.LAN]: 

# 设置 LDAP 目录管理员密码(与 Windows Active Directory 还原目录密码类似)
Certain directory server operations require an administrative user.
This user is referred to as the Directory Manager and has full access
to the Directory for system management tasks and will be added to the
instance of directory server created for IPA.
The password must be at least 8 characters long.
Directory Manager password: 
Password (confirm): 

# 设置 IPA 服务器管理员 admin 的密码
The IPA server requires an administrative user, named 'admin'.
This user is a regular system account used for IPA server administration.
IPA admin password: 
Password (confirm): 

# IPv6 不可用,忽略
Invalid IP address fe80::42:27ff:fe50:c16 for ldap-001.rockylinux.lan: cannot use link-local IP address fe80::42:27ff:fe50:c16
Invalid IP address fe80::486a:e224:31e4:d1fc for ldap-001.rockylinux.lan: cannot use link-local IP address fe80::486a:e224:31e4:d1fc
Trust is configured but no NetBIOS domain name found, setting it now.

# 设置 NetBIOS 域名
Enter the NetBIOS name for the IPA domain.
Only up to 15 uppercase ASCII letters, digits and dashes are allowed.
Example: EXAMPLE.
NetBIOS domain name [ROCKYLINUX]: 

# 配置是否启用 chrony 服务器,因为木子有单独的 chrony 时间服务器,所以这里使用默认 no
Do you want to configure chrony with NTP server or pool address? [no]: 

# 输出前面的设置,并确认没有问题后,输入 yes,开始安装
The IPA Master Server will be configured with:
Hostname:       ldap-001.rockylinux.lan
IP address(es): 192.168.1.3
Domain name:    rockylinux.lan
Realm name:     ROCKYLINUX.LAN

The CA will be configured with:
Subject DN:   CN=Certificate Authority,O=ROCKYLINUX.LAN
Subject base: O=ROCKYLINUX.LAN
Chaining:     self-signed

Continue to configure the system with these values? [no]: yes

# 开始安装,整体过程需要几分钟
The following operations may take some minutes to complete.
Please wait until the prompt is returned.
.....(略)

# 出现以下信息,说明安装成功
Next steps:
        # 1. 需要配置防火墙开启以下端口
        1. You must make sure these network ports are open:
                TCP Ports:
                  * 80, 443: HTTP/HTTPS
                  * 389, 636: LDAP/LDAPS
                  * 88, 464: kerberos
                  * 53: bind
                UDP Ports:
                  * 88, 464: kerberos
                  * 53: bind
                  * 123: ntp
        # 2. 可以通过 ipa 命令或者 WebUI 进行用户、组、计算机等管理
        2. You can now obtain a kerberos ticket using the command: 'kinit admin'
           This ticket will allow you to use the IPA tools (e.g., ipa user-add)
           and the web user interface.

Be sure to back up the CA certificates stored in /root/cacert.p12
These files are required to create replicas. The password for these
files is the Directory Manager password
The ipa-server-install command was successful

# 如果您在安装过程中,出现任何异常问题,可以使用以下命令卸载,再重装安装
[root@ldap-001 ~]# ipa-server-install --uninstall

# 升级
[root@ldap-001 ~]# ipa-server-upgrade

防火墙配置

FreeIPA 常用端口如下:

服务 端口 协议 备注
HTTP/HTTPS 80,443 TCP FreeIPA WebUI
LDAP/LDAPS 389,636 TCP 其它客户端通过 LDAP 或 LDAPS 协议与服务器端进行认证
Kerberos 88,464 TCP 和 UDP Kerberos 客户端与服务器端加密通讯认证
DNS 53 TCP 和 UDP 木子这里未使用 FreeIPA 自带的 DNS,所以不需要配置此端口。
NTP 123 UDP 木子这里未使用 FreeIPA 自带的 NTP,所以不需要配置此端口。

 

Rocky Linux 提供了 freeipa-4 防火墙服务,用于开启 FreeIPA 所需的相关端口,包括:http、https、kerberos、kpasswd、ldap、ldaps 等。具体端口信息可参考:/usr/lib/firewalld/services/freeipa-4.xml。此外,也可以根据实际需求,单独设置某个服务端口,例如:freeipa-ldapfreeipa-ldaps

[root@ldap-001 ~]# cat /usr/lib/firewalld/services/freeipa-4.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>FreeIPA 4 server</short>
  <description>FreeIPA is an integrated identity and authentication solution with Kerberos, LDAP, PKI, and web UI. Enable this option if you plan to provide a FreeIPA server. Enable the 'dns' service if this FreeIPA server provides DNS services, 'ntp' service if this FreeIPA server provides NTP services, and 'freeipa-trust' for cross-forest trusts with Active Directory.</description>
  <!-- CRL and OCSP -->
  <include service="http"/>
  <!-- API and web UI -->
  <include service="https"/>
  <include service="kerberos"/>
  <include service="kpasswd"/>
  <include service="ldap"/>
  <include service="ldaps"/>
</service>

[root@ldap-001 ~]# ls -l /usr/lib/firewalld/services/freeipa-*
-rw-r--r-- 1 root root 709 Feb  4 17:33 /usr/lib/firewalld/services/freeipa-4.xml
-rw-r--r-- 1 root root 488 Feb  4 17:33 /usr/lib/firewalld/services/freeipa-ldap.xml
-rw-r--r-- 1 root root 489 Feb  4 17:33 /usr/lib/firewalld/services/freeipa-ldaps.xml
-rw-r--r-- 1 root root 242 Feb  4 17:33 /usr/lib/firewalld/services/freeipa-replication.xml
-rw-r--r-- 1 root root 657 Feb  4 17:33 /usr/lib/firewalld/services/freeipa-trust.xml

# 开启所有端口
[root@ldap-001 ~]# firewall-cmd --permanent --add-service=freeipa-4

# 只启用 ldap 认证端口
[root@ldap-001 ~]# firewall-cmd --permanent --add-service=freeipa-ldap
[root@ldap-001 ~]# firewall-cmd --permanent --add-service=freeipa-ldaps

# 生效配置
[root@ldap-001 ~]# firewall-cmd --reload

# 确保配置生效
[root@ldap-001 ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens18
  sources: 
  services: cockpit dhcpv6-client freeipa-4 freeipa-ldap freeipa-ldaps ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

SELinux 配置

如果您处于内网环境且对安全性要求不高,可以选择禁用 SELinux。若需要启用 SELinux,也可以参考官方文档:Integration_with_SELinux — FreeIPA documentation 进行相应配置。

验证服务可用性

FreeIPA 服务的可用性可以从两个维度进行验证:

  1. 通过 systemctl 检查各相关服务本身的运行状态;
  2. 确认 FreeIPA 的 LDAP 服务能否正常提供查询和认证功能。

检查服务状态

# Directory Service(注意 dirsrv@REALM 名称)
systemctl status [email protected]

# krb5kdc Service
systemctl status krb5kdc

# kadmin Service
systemctl status kadmin

# httpd Service
systemctl status httpd

# ipa-custodia Service
systemctl status ipa-custodia

# pki-tomcatd Service
systemctl status [email protected]

# ipa-otpd Service
systemctl status ipa-otpd.socket

# ipa-ccache-sweep Service 
systemctl status ipa-ccache-sweep.service 

# 确保以上服务的端口都正常监听
[root@ldap ~]# netstat -tulnp | grep -E "389|636|80|443|88|464|8080|8443"
tcp        0      0 0.0.0.0:749             0.0.0.0:*               LISTEN      1480/kadmind        
tcp        0      0 0.0.0.0:464             0.0.0.0:*               LISTEN      1480/kadmind        
tcp        0      0 0.0.0.0:88              0.0.0.0:*               LISTEN      1471/krb5kdc        
tcp6       0      0 :::749                  :::*                    LISTEN      1480/kadmind        
tcp6       0      0 :::636                  :::*                    LISTEN      1433/ns-slapd       
tcp6       0      0 :::443                  :::*                    LISTEN      1490/httpd          
tcp6       0      0 :::389                  :::*                    LISTEN      1433/ns-slapd       
tcp6       0      0 :::464                  :::*                    LISTEN      1480/kadmind        
tcp6       0      0 :::8443                 :::*                    LISTEN      1801/java           
tcp6       0      0 :::88                   :::*                    LISTEN      1471/krb5kdc        
tcp6       0      0 :::80                   :::*                    LISTEN      1490/httpd          
tcp6       0      0 127.0.0.1:8009          :::*                    LISTEN      1801/java           
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      1801/java           
tcp6       0      0 ::1:8009                :::*                    LISTEN      1801/java           
tcp6       0      0 :::8080                 :::*                    LISTEN      1801/java           
udp        0      0 0.0.0.0:464             0.0.0.0:*                           1480/kadmind        
udp        0      0 0.0.0.0:88              0.0.0.0:*                           1471/krb5kdc        
udp6       0      0 :::464                  :::*                                1480/kadmind        
udp6       0      0 :::88                   :::*                                1471/krb5kdc 

# 查看 ipa 服务状态
[root@ldap-001 ~]# systemctl status ipa
● ipa.service - Identity, Policy, Audit
     Loaded: loaded (/usr/lib/systemd/system/ipa.service; enabled; preset: disabled)
     Active: active (exited) since Tue 2025-06-01 11:42:31 CST; 4h 5min ago
   Main PID: 848 (code=exited, status=0/SUCCESS)
        CPU: 4.781s

Jun 1 11:41:48 ldap-001.rockylinux.lan systemd[1]: Starting Identity, Policy, Audit...
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: ipa: INFO: The ipactl command was successful
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting Directory Service
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting krb5kdc Service
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting kadmin Service
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting httpd Service
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting ipa-custodia Service
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting pki-tomcatd Service
Jun 1 11:42:31 ldap-001.rockylinux.lan ipactl[848]: Starting ipa-otpd Service
Jun 1 11:42:31 ldap-001.rockylinux.lan systemd[1]: Finished Identity, Policy, Audit.

# 确保所有服务状态是正常的
[root@ldap-001 ~]# ipactl status
Directory Service: RUNNING
krb5kdc Service: RUNNING
kadmin Service: RUNNING
httpd Service: RUNNING
ipa-custodia Service: RUNNING
pki-tomcatd Service: RUNNING
ipa-otpd Service: RUNNING
ipa: INFO: The ipactl command was successful

检查服务功能

除了检查 FreeIPA 相关服务是否正常运行外,还可以通过以下命令进一步验证各核心功能:

  • 使用 ldapsearch 命令进行LDAP 查询,以确认 Directory Service 是否工作正常;
  • 使用 kinit 命令获取 Kerberos 票据,以验证 krb5kdc 和 kadmin 服务的可用性。
# DN 可用性验证
[root@ldap-001 ~]# ldapsearch -x dc=rockylinux
# extended LDIF
# LDAPv3
# base <dc=rockylinux,dc=lan> (default) with scope subtree
# filter: dc=rockylinux
# requesting: ALL
# rockylinux.lan
dn: dc=rockylinux,dc=lan
objectClass: top
objectClass: domain
objectClass: pilotObject
objectClass: domainRelatedObject
objectClass: nisDomainObject
dc: rockylinux
info: IPA V2.0
nisDomain: rockylinux.lan
associatedDomain: rockylinux.lan
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1

# Kerberos 票据获取(验证 krb5kdc、kadmin)
[root@ldap-001 ~]# kinit admin
Password for [email protected]: 
[root@ldap-001 ~]# klist
Ticket cache: KCM:0
Default principal: [email protected]
Valid starting     Expires            Service principal
06/01/25 19:46:59  06/02/25 19:08:33  krbtgt/[email protected]

用户管理

过去,用户管理常常需要借助 ldapaddldaplistldapmodifyldapdelete 等命令,操作流程繁琐且复杂(详细参考 LDAP 名称服务的设置和管理)。现在,FreeIPA 提供了统一的 ipa 命令行工具,大幅简化了用户、主机、服务、DNS、证书等的集中管理,有效提升了系统运维效率,并降低了 LDAP 管理的门槛。此外,FreeIPA 还支持 Web 管理界面(Web UI),为习惯图形化操作的管理员提供了便利。
使用 ipa 命令前,需要通过 Kerberos 进行管理员身份验证。具体操作是在 ldap.rockylinux.lan 服务器上执行 kinit admin,输入安装 FreeIPA 时设定的管理员密码,获取 Kerberos 票据后即可进行各种管理操作。

# 所有用户管理命令
[root@ldap-001 ~]# ipa help commands | grep user- | grep -Ev "stage|idoverrideuser"
user-add                  添加新用户
user-add-cert             向用户条目中添加一个或多个证书
user-add-certmapdata      向用户条目中添加一个或多个证书映射信息
user-add-manager          为用户条目添加一个管理者(直属上级)
user-add-passkey          向用户条目中添加一个或多个密钥设备映射(如FIDO Passkey)
user-add-principal        向用户条目添加新的主体别名(principal alias)

user-del                  删除用户
user-disable              禁用用户账户
user-enable               启用用户账户
user-find                 搜索用户
user-mod                  修改用户

user-remove-cert          从用户条目中移除一个或多个证书
user-remove-certmapdata   从用户条目中移除一个或多个证书映射信息
user-remove-manager       从用户条目中移除管理者(直属上级)
user-remove-passkey       从用户条目中移除一个或多个密钥设备映射
user-remove-principal     从用户条目中移除主体别名

user-show                 显示用户详细信息
user-status               显示用户账户的锁定状态
user-undel                恢复被删除的用户账户
user-unlock               解锁用户账户

# 获取管理员票据
[root@ldap-001 ~]# kinit admin
Password for [email protected]: 

# 查看当前用户的 Kerberos 票据(Ticket)信息
[root@ldap-001 ~]# klist
Ticket cache: KCM:0
Default principal: [email protected]

# 开始时间,到期时间(有效期 24 小时,到期后,需要重新登录)
Valid starting     Expires            Service principal
06/01/25 14:23:56  06/02/25 14:13:38  krbtgt/[email protected]

# 添加新用户
# ipa user-add 登录用户名 --first=名 --last=姓
[root@ldap-001 ~]# ipa user-add muzilee --first=muzi --last=lee
--------------------
Added user "muzilee"
--------------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Full name: muzi lee
  Display name: muzi lee
  Initials: ml
  Home directory: /home/muzilee
  GECOS: muzi lee
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected] # 注意邮箱地址,后续变更对应用户属性
  UID: 608200004
  GID: 608200004
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

# 查询所有用户
[root@ldap-001 ~]# ipa user-find
---------------
2 users matched
---------------
  User login: admin
  Last name: Administrator
  Home directory: /home/admin
  Login shell: /bin/bash
  Principal name: [email protected]
  Principal alias: [email protected], [email protected]
  UID: 608200000
  GID: 608200000
  Account disabled: False

  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /home/muzilee
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200004
  GID: 608200004
  Account disabled: False
----------------------------
Number of entries returned 2
----------------------------

# 查询指定用户(不管是查询登录用户名、名或姓,都可以查询到)
[root@ldap-001 ~]# ipa user-find muzilee
--------------
1 user matched
--------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /home/muzilee
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200004
  GID: 608200004
  Account disabled: False
----------------------------
Number of entries returned 1
----------------------------

[root@ldap-001 ~]# ipa user-find muzi
--------------
1 user matched
--------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /home/muzilee
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200004
  GID: 608200004
  Account disabled: False
----------------------------
Number of entries returned 1
----------------------------

[root@ldap-001 ~]# ipa user-find lee
--------------
1 user matched
--------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /home/muzilee
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200004
  GID: 608200004
  Account disabled: False
----------------------------
Number of entries returned 1
----------------------------

# 如果查询的用户不存在,返回为 0
[root@ldap-001 ~]# ipa user-find haozi
---------------
0 users matched
---------------
----------------------------
Number of entries returned 0
----------------------------

# 修改用户属性
# ipa user-mod 登录用户名 [email protected]
[root@ldap-001 ~]#  ipa user-mod muzilee [email protected]
-----------------------
Modified user "muzilee"
-----------------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /home/muzilee
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected] # 邮箱地址
  UID: 608200004
  GID: 608200004
  Account disabled: False
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

# 怎么知道对应属性的参数名称了,比如:Email address 等于 --email
# 我们可以通过 ipa help user-mod 获取 ipa 修改用户信息的相关参数
# 修改家目录为 /ldaphome/muzilee
[root@ldap-001 ~]# ipa user-mod muzilee --homedir=/ldaphome/muzilee
-----------------------
Modified user "muzilee"
-----------------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /ldaphome/muzilee # home 目录
  Login shell: /bin/sh
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200004
  GID: 608200004
  Account disabled: False
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

# 修改默认 shell 为 /bin/bash
[root@ldap-001 ~]# ipa user-mod muzilee --shell=/bin/bash
-----------------------
Modified user "muzilee"
-----------------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /ldaphome/muzilee
  Login shell: /bin/bash # 默认 Shell
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200004
  GID: 608200004
  Account disabled: False
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

# 查看用户详细信息
[root@ldap-001 ~]# ipa user-show muzilee
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /ldaphome/muzilee
  Login shell: /bin/bash
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected] # 邮箱
  UID: 608200006
  GID: 608200006
  Account disabled: False
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

# 默认新建用户是没有密码的,可以通过以下命令设置密码
[root@ldap-001 ~]# echo k2PO3cY4fFGjFS | ipa user-mod muzilee --password
-----------------------
Modified user "muzilee"
-----------------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Home directory: /ldaphome/muzilee
  Login shell: /bin/bash
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200006
  GID: 608200006
  Account disabled: False
  Password: True # 表示设置密码成功
  Member of groups: ipausers
  Kerberos keys available: True

# 查看组用户
[root@ldap-001 ~]# ipa group-show admins
  Group name: admins
  Description: Account administrators group
  GID: 608200000
  Member users: admin # 只有 admin 一个账号

# 添加 muzilee 至 admins 组,当然也可以通过参数 group-add 添加组
[root@ldap-001 ~]# ipa group-add-member admins --user=muzilee
  Group name: admins
  Description: Account administrators group
  GID: 608200000
  Member users: admin, muzilee
-------------------------
Number of members added 1
-------------------------

# 删除用户
# ipa user-del 登录用户名
[root@ldap-001 ~]# ipa user-del muzilee
----------------------
Deleted user "muzilee"
----------------------

# 当然也可以通过 ldapsearch 命令,查询用户信息
[root@ldap-001 ~]# ldapsearch -x uid=admin
# extended LDIF
#
# LDAPv3
# base <dc=rockylinux,dc=lan> (default) with scope subtree
# filter: uid=admin
# requesting: ALL
#

# admin, users, compat, rockylinux.lan
dn: uid=admin,cn=users,cn=compat,dc=rockylinux,dc=lan
objectClass: posixAccount
objectClass: ipaOverrideTarget
objectClass: top
gecos: Administrator
cn: Administrator
uidNumber: 608200000
gidNumber: 608200000
loginShell: /bin/bash
homeDirectory: /home/admin
ipaAnchorUUID:: OklQQTpyb2NreWxpbnV4LmxhbjoyMzEzM2M1ZS01MGE2LTExZjAtYWE5Ny01Mm
 U5ZWI3NzNkZmU=
uid: admin

# admin, users, accounts, rockylinux.lan
dn: uid=admin,cn=users,cn=accounts,dc=rockylinux,dc=lan
objectClass: top
objectClass: person
objectClass: posixaccount
objectClass: krbprincipalaux
objectClass: krbticketpolicyaux
objectClass: inetuser
objectClass: ipaobject
objectClass: ipasshuser
objectClass: ipaSshGroupOfPubKeys
objectClass: ipaNTUserAttrs
uid: admin
cn: Administrator
sn: Administrator
uidNumber: 608200000
gidNumber: 608200000
homeDirectory: /home/admin
loginShell: /bin/bash
gecos: Administrator
ipaNTSecurityIdentifier: S-1-5-21-3223399076-1772250745-127116554-500

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

注意:可以看到 admin 用户信息在 cn=accountscn=compat 中同时存在,本质两个用户是同一个,之所以会出现两个不同账号,是为了兼容各种不同需求的客户端和服务。

全局属性设置

前面我们使用 ipa user-mod muzilee --homedir=/ldaphome/muzilee 修改的只是单个用户的属性,如果需要全局设置,可以使用 ipa config-mod 命令。

# 参数说明
[root@ldap-001 ~]# ipa help config-mod
用法: ipa [全局选项] config-mod [选项]
用于修改FreeIPA的配置选项。

选项说明:
  -h, --help                  显示此帮助信息并退出
  --maxusername=INT           用户名最大长度
  --maxhostname=INT           主机名最大长度
  --homedirectory=STR         默认的用户家目录路径
  --defaultshell=STR          新用户默认的Shell
  --defaultgroup=STR          新用户默认所属的组
  --emaildomain=STR           默认的电子邮件域名
  --searchtimelimit=INT       搜索操作的最大时长(秒),-1或0表示不限时
  --searchrecordslimit=INT    搜索返回的最大记录数,-1或0表示不限制
  --usersearch=STR            用户搜索时可用于查找的字段列表(以逗号分隔)
  --groupsearch=STR           组搜索时可用于查找的字段列表(以逗号分隔)
  --enable-migration=BOOL     是否启用迁移模式
  --groupobjectclasses=STR    组的默认ObjectClass(以逗号分隔的列表)
  --userobjectclasses=STR     用户的默认ObjectClass(以逗号分隔的列表)
  --pwdexpnotify=INT          密码即将过期前的提醒天数
  --ipaconfigstring=['AllowNThash', 'KDC:Disable Last Success', 'KDC:Disable Lockout', 
                     'KDC:Disable Default Preauth for SPNs', 'EnforceLDAPOTP']
                               密码插件生成的额外哈希选项
  --ipaselinuxusermaporder=STR
                               SELinux用户优先级顺序(用 $ 分隔)
  --ipaselinuxusermapdefault=STR
                               当SELinux映射规则没有匹配时,默认使用的SELinux用户
  --pac-type=['MS-PAC', 'PAD', 'nfs:NONE']
                               服务默认支持的PAC类型
  --user-auth-type=['password', 'radius', 'otp', 'pkinit', 'hardened', 'idp', 'passkey', 'disabled']
                               默认支持的用户认证类型
  --user-default-subid=BOOL   新用户是否默认分配subid(子ID)
  --ca-renewal-master-server=STR
                               IPA证书颁发机构(CA)续期主服务器
  --domain-resolution-order=STR
                               用冒号“:”分隔的域名列表,用于短名自动限定
  --enable-sid                新用户和新组自动分配SID
  --add-sids                  为已有用户和组分配SID
  --netbios-name=STR          IPA域的NetBIOS名字
  --setattr=STR               设置属性键值对,格式为“属性=值”。多值属性将替换全部现有值
  --addattr=STR               新增属性键值对,格式为“属性=值”。属性必须符合schema定义
  --delattr=STR               删除属性键值对。此项在所有设置和添加操作完成后才被执行
  --rights                    显示该条目的访问权限(需与 --all 一起使用)。更多细节见ipa手册
  --all                       从服务器获取并显示所有属性,影响命令输出
  --raw                       按服务器中实际存储格式打印条目,仅影响输出格式

# 修改默认家目录
[root@ldap-001 ~]# ipa config-mod --homedirectory=/ldaphome
  Maximum username length: 32
  Maximum hostname length: 64
  Home directory base: /ldaphome
  Default shell: /bin/sh
  Default users group: ipausers
  Default e-mail domain: rockylinux.lan
  Search time limit: 2
  Search size limit: 100
  User search fields: uid,givenname,sn,telephonenumber,ou,title
  Group search fields: cn,description
  Enable migration mode: False
  Certificate Subject base: O=ROCKYLINUX.LAN
  Password Expiration Notification (days): 4
  Password plugin features: AllowNThash, KDC:Disable Last Success
  SELinux user map order: guest_u:s0$xguest_u:s0$user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023
  Default SELinux user: unconfined_u:s0-s0:c0.c1023
  Default PAC types: MS-PAC, nfs:NONE
  IPA masters: ldap-001.rockylinux.lan
  IPA master capable of PKINIT: ldap-001.rockylinux.lan
  IPA CA servers: ldap-001.rockylinux.lan
  IPA CA renewal master: ldap-001.rockylinux.lan

# 修改默认 Shell
[root@ldap-001 ~]# ipa config-mod --defaultshell=/bin/bash
  Maximum username length: 32
  Maximum hostname length: 64
  Home directory base: /ldaphome
  Default shell: /bin/bash
  Default users group: ipausers
  Default e-mail domain: rockylinux.lan
  Search time limit: 2
  Search size limit: 100
  User search fields: uid,givenname,sn,telephonenumber,ou,title
  Group search fields: cn,description
  Enable migration mode: False
  Certificate Subject base: O=ROCKYLINUX.LAN
  Password Expiration Notification (days): 4
  Password plugin features: AllowNThash, KDC:Disable Last Success
  SELinux user map order: guest_u:s0$xguest_u:s0$user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023
  Default SELinux user: unconfined_u:s0-s0:c0.c1023
  Default PAC types: MS-PAC, nfs:NONE
  IPA masters: ldap-001.rockylinux.lan
  IPA master capable of PKINIT: ldap-001.rockylinux.lan
  IPA CA servers: ldap-001.rockylinux.lan
  IPA CA renewal master: ldap-001.rockylinux.lan

# 修改 Email 域名
[root@ldap-001 ~]# ipa config-mod --emaildomain=vip.rockylinux.cn
  Maximum username length: 32
  Maximum hostname length: 64
  Home directory base: /ldaphome
  Default shell: /bin/bash
  Default users group: ipausers
  Default e-mail domain: vip.rockylinux.cn
  Search time limit: 2
  Search size limit: 100
  User search fields: uid,givenname,sn,telephonenumber,ou,title
  Group search fields: cn,description
  Enable migration mode: False
  Certificate Subject base: O=ROCKYLINUX.LAN
  Password Expiration Notification (days): 4
  Password plugin features: AllowNThash, KDC:Disable Last Success
  SELinux user map order: guest_u:s0$xguest_u:s0$user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023
  Default SELinux user: unconfined_u:s0-s0:c0.c1023
  Default PAC types: MS-PAC, nfs:NONE
  IPA masters: ldap-001.rockylinux.lan
  IPA master capable of PKINIT: ldap-001.rockylinux.lan
  IPA CA servers: ldap-001.rockylinux.lan
  IPA CA renewal master: ldap-001.rockylinux.lan

# 此时我们再创建用户,对应用户的 Home directory、Login Shell、Email address 地址后缀,就变成我们全局设置的。
[root@ldap-001 ~]# ipa user-add muzilee --first=muzi --last=lee
--------------------
Added user "muzilee"
--------------------
  User login: muzilee
  First name: muzi
  Last name: lee
  Full name: muzi lee
  Display name: muzi lee
  Initials: ml
  Home directory: /ldaphome/muzilee
  GECOS: muzi lee
  Login shell: /bin/bash
  Principal name: [email protected]
  Principal alias: [email protected]
  Email address: [email protected]
  UID: 608200006
  GID: 608200006
  Password: False
  Member of groups: ipausers
  Kerberos keys available: False

ipa 命令

ipa 命令拥有丰富的参数和选项,建议在实际使用过程中结合需求逐步学习和掌握。

[root@ldap-001 ~]# ipa help topics
automember         Auto Membership Rule.
automount          Automount
ca                 Manage Certificate Authorities
caacl              Manage CA ACL rules.
cert               IPA certificate operations
certmap            Certificate Identity Mapping
certprofile        Manage Certificate Profiles
config             Server configuration
delegation         Group to Group Delegation
dns                Domain Name System (DNS)
domainlevel        Raise the IPA Domain Level.
group              Groups of users
hbac               Host-based access control commands
hbactest           Simulate use of Host-based access controls
host               Hosts/Machines
hostgroup          Groups of hosts.
idp                External Identity Provider References
idrange            ID ranges
idviews            ID Views
krbtpolicy         Kerberos ticket policy
location           IPA locations
migration          Migration to IPA
misc               Misc plug-ins
netgroup           Netgroups
otp                One time password commands
passkeyconfig      Passkey configuration
passwd             Set a user''s password
permission         Permissions
ping               Ping the remote IPA server to ensure it is running.
pkinit             Kerberos PKINIT feature status reporting tools.
privilege          Privileges
pwpolicy           Password policy
radiusproxy        RADIUS Proxy Servers
realmdomains       Realm domains
role               Roles
schema             API Schema
selfservice        Self-service Permissions
selinuxusermap     SELinux User Mapping
server             IPA servers
serverrole         IPA server roles
service            Services
servicedelegation  Service Constrained Delegation
stageuser          Stageusers
subid              Subordinate ids
sudo               commands for controlling sudo configuration
topology           Topology
trust              Cross-realm trusts
user               Users
vault              Vaults

# 按 Table 键,获取所有命令
[root@ldap-001 ~]# ipa 
Display all 457 possibilities? (y or n)
automember-add                         command-show                           help                                   otptoken-add                           service-add-delegation                 sudorule-disable
automember-add-condition               config-mod                             host-add                               otptoken-add-managedby                 service-add-host                       sudorule-enable
automember-default-group-remove        config-show                            host-add-cert                          otptoken-add-yubikey                   service-add-principal                  sudorule-find
automember-default-group-set           console                                host-add-delegation                    otptoken-del                           service-add-smb                        sudorule-mod
automember-default-group-show          delegation-add                         host-add-managedby                     otptoken-find                          service-allow-add-delegation           sudorule-remove-allow-command
automember-del                         delegation-del                         host-add-principal                     otptoken-mod                           service-allow-create-keytab            sudorule-remove-deny-command
automember-find                        delegation-find                        host-allow-add-delegation              otptoken-remove-managedby              service-allow-retrieve-keytab          sudorule-remove-host
automember-find-orphans                delegation-mod                         host-allow-create-keytab               otptoken-show                          service-del                            sudorule-remove-option
automember-mod                         delegation-show                        host-allow-retrieve-keytab             otptoken-sync                          service-disable                        sudorule-remove-runasgroup
automember-rebuild                     dns-update-system-records              host-del                               output-find                            service-disallow-add-delegation        sudorule-remove-runasuser
automember-remove-condition            dnsconfig-mod                          host-disable                           output-show                            service-disallow-create-keytab         sudorule-remove-user
automember-show                        dnsconfig-show                         host-disallow-add-delegation           param-find                             service-disallow-retrieve-keytab       sudorule-show
automountkey-add                       dnsforwardzone-add                     host-disallow-create-keytab            param-show                             service-find                           topic-find
automountkey-del                       dnsforwardzone-add-permission          host-disallow-retrieve-keytab          passkeyconfig-mod                      service-mod                            topic-show
automountkey-find                      dnsforwardzone-del                     host-find                              passkeyconfig-show                     service-remove-cert                    topologysegment-add
automountkey-mod                       dnsforwardzone-disable                 host-mod                               passwd                                 service-remove-delegation              topologysegment-del
automountkey-show                      dnsforwardzone-enable                  host-remove-cert                       permission-add                         service-remove-host                    topologysegment-find
automountlocation-add                  dnsforwardzone-find                    host-remove-delegation                 permission-del                         service-remove-principal               topologysegment-mod
automountlocation-del                  dnsforwardzone-mod                     host-remove-managedby                  permission-find                        service-show                           topologysegment-reinitialize
automountlocation-find                 dnsforwardzone-remove-permission       host-remove-principal                  permission-mod                         servicedelegationrule-add              topologysegment-show
automountlocation-import               dnsforwardzone-show                    host-show                              permission-show                        servicedelegationrule-add-member       topologysuffix-find
automountlocation-show                 dnsrecord-add                          hostgroup-add                          ping                                   servicedelegationrule-add-target       topologysuffix-show
automountlocation-tofiles              dnsrecord-del                          hostgroup-add-member                   pkinit-status                          servicedelegationrule-del              topologysuffix-verify
automountmap-add                       dnsrecord-find                         hostgroup-add-member-manager           plugins                                servicedelegationrule-find             trust-add
automountmap-add-indirect              dnsrecord-mod                          hostgroup-del                          privilege-add                          servicedelegationrule-remove-member    trust-del
automountmap-del                       dnsrecord-show                         hostgroup-find                         privilege-add-permission               servicedelegationrule-remove-target    trust-fetch-domains
automountmap-find                      dnsserver-find                         hostgroup-mod                          privilege-del                          servicedelegationrule-show             trust-find
automountmap-mod                       dnsserver-mod                          hostgroup-remove-member                privilege-find                         servicedelegationtarget-add            trust-mod
automountmap-show                      dnsserver-show                         hostgroup-remove-member-manager        privilege-mod                          servicedelegationtarget-add-member     trust-show
ca-add                                 dnszone-add                            hostgroup-show                         privilege-remove-permission            servicedelegationtarget-del            trustconfig-mod
ca-del                                 dnszone-add-permission                 idoverridegroup-add                    privilege-show                         servicedelegationtarget-find           trustconfig-show
ca-disable                             dnszone-del                            idoverridegroup-del                    pwpolicy-add                           servicedelegationtarget-remove-member  trustdomain-del
ca-enable                              dnszone-disable                        idoverridegroup-find                   pwpolicy-del                           servicedelegationtarget-show           trustdomain-disable
ca-find                                dnszone-enable                         idoverridegroup-mod                    pwpolicy-find                          show-mappings                          trustdomain-enable
ca-mod                                 dnszone-find                           idoverridegroup-show                   pwpolicy-mod                           stageuser-activate                     trustdomain-find
ca-show                                dnszone-mod                            idoverrideuser-add                     pwpolicy-show                          stageuser-add                          user-add
caacl-add                              dnszone-remove-permission              idoverrideuser-add-cert                radiusproxy-add                        stageuser-add-cert                     user-add-cert
caacl-add-ca                           dnszone-show                           idoverrideuser-del                     radiusproxy-del                        stageuser-add-certmapdata              user-add-certmapdata
caacl-add-host                         domainlevel-get                        idoverrideuser-find                    radiusproxy-find                       stageuser-add-manager                  user-add-manager
caacl-add-profile                      domainlevel-set                        idoverrideuser-mod                     radiusproxy-mod                        stageuser-add-passkey                  user-add-passkey
caacl-add-service                      env                                    idoverrideuser-remove-cert             radiusproxy-show                       stageuser-add-principal                user-add-principal
caacl-add-user                         group-add                              idoverrideuser-show                    realmdomains-mod                       stageuser-del                          user-del
caacl-del                              group-add-member                       idp-add                                realmdomains-show                      stageuser-find                         user-disable
caacl-disable                          group-add-member-manager               idp-del                                role-add                               stageuser-mod                          user-enable
caacl-enable                           group-del                              idp-find                               role-add-member                        stageuser-remove-cert                  user-find
caacl-find                             group-detach                           idp-mod                                role-add-privilege                     stageuser-remove-certmapdata           user-mod
caacl-mod                              group-find                             idp-show                               role-del                               stageuser-remove-manager               user-remove-cert
caacl-remove-ca                        group-mod                              idrange-add                            role-find                              stageuser-remove-passkey               user-remove-certmapdata
caacl-remove-host                      group-remove-member                    idrange-del                            role-mod                               stageuser-remove-principal             user-remove-manager
caacl-remove-profile                   group-remove-member-manager            idrange-find                           role-remove-member                     stageuser-show                         user-remove-passkey
caacl-remove-service                   group-show                             idrange-mod                            role-remove-privilege                  subid-find                             user-remove-principal
caacl-remove-user                      hbacrule-add                           idrange-show                           role-show                              subid-generate                         user-show
caacl-show                             hbacrule-add-host                      idview-add                             selfservice-add                        subid-match                            user-stage
cert-find                              hbacrule-add-service                   idview-apply                           selfservice-del                        subid-mod                              user-status
cert-remove-hold                       hbacrule-add-user                      idview-del                             selfservice-find                       subid-show                             user-undel
cert-request                           hbacrule-del                           idview-find                            selfservice-mod                        subid-stats                            user-unlock
cert-revoke                            hbacrule-disable                       idview-mod                             selfservice-show                       sudocmd-add                            vault-add
cert-show                              hbacrule-enable                        idview-show                            selinuxusermap-add                     sudocmd-del                            vault-add-member
cert-status                            hbacrule-find                          idview-unapply                         selinuxusermap-add-host                sudocmd-find                           vault-add-owner
certmap-match                          hbacrule-mod                           krbtpolicy-mod                         selinuxusermap-add-user                sudocmd-mod                            vault-archive
certmapconfig-mod                      hbacrule-remove-host                   krbtpolicy-reset                       selinuxusermap-del                     sudocmd-show                           vault-del
certmapconfig-show                     hbacrule-remove-service                krbtpolicy-show                        selinuxusermap-disable                 sudocmdgroup-add                       vault-find
certmaprule-add                        hbacrule-remove-user                   location-add                           selinuxusermap-enable                  sudocmdgroup-add-member                vault-mod
certmaprule-del                        hbacrule-show                          location-del                           selinuxusermap-find                    sudocmdgroup-del                       vault-remove-member
certmaprule-disable                    hbacsvc-add                            location-find                          selinuxusermap-mod                     sudocmdgroup-find                      vault-remove-owner
certmaprule-enable                     hbacsvc-del                            location-mod                           selinuxusermap-remove-host             sudocmdgroup-mod                       vault-retrieve
certmaprule-find                       hbacsvc-find                           location-show                          selinuxusermap-remove-user             sudocmdgroup-remove-member             vault-show
certmaprule-mod                        hbacsvc-mod                            migrate-ds                             selinuxusermap-show                    sudocmdgroup-show                      vaultconfig-show
certmaprule-show                       hbacsvc-show                           netgroup-add                           server-del                             sudorule-add                           vaultcontainer-add-owner
certprofile-del                        hbacsvcgroup-add                       netgroup-add-member                    server-find                            sudorule-add-allow-command             vaultcontainer-del
certprofile-find                       hbacsvcgroup-add-member                netgroup-del                           server-mod                             sudorule-add-deny-command              vaultcontainer-remove-owner
certprofile-import                     hbacsvcgroup-del                       netgroup-find                          server-role-find                       sudorule-add-host                      vaultcontainer-show
certprofile-mod                        hbacsvcgroup-find                      netgroup-mod                           server-role-show                       sudorule-add-option                    
certprofile-show                       hbacsvcgroup-mod                       netgroup-remove-member                 server-show                            sudorule-add-runasgroup                
class-find                             hbacsvcgroup-remove-member             netgroup-show                          server-state                           sudorule-add-runasuser                 
class-show                             hbacsvcgroup-show                      otpconfig-mod                          service-add                            sudorule-add-user                      
command-find                           hbactest                               otpconfig-show                         service-add-cert                       sudorule-del                           

# 查询所有命令详细信息
[root@ldap-001 ~]# ipa help commands
automember-add  Add an automember rule.
automember-add-condition  Add conditions to an automember rule.
automember-default-group-remove  Remove default (fallback) group for all unmatched entries.
automember-default-group-set     Set default (fallback) group for all unmatched entries.
automember-default-group-show    Display information about the default (fallback) automember groups.
automember-del                   Delete an automember rule.
automember-find                  Search for automember rules.
.....(略)

FreeIPA Web UI

前面提到的全局属性设置,以及用户、组、计算机等对象的增删改查,都可以通过 FreeIPA 提供的 Web UI 完成。您只需在浏览器中访问 https://ldap-001.rockylinux.lan 即可。需要注意的是,由于使用的是 FreeIPA 自签发的 TLS 证书,浏览器可能会提示连接不安全。此时,您可以将该证书导入本地信任列表,以提升浏览器连接的安全性。

用户名:admin
密码:xxx

详细用户管理界面:

后续,木子将结合 Let’s Encrypt,讲解如何为 FreeIPA Web UI 配置 SSL/TLS 证书。

参考文献

[1] Quick_Start_Guide — FreeIPA documentation
[2] docs.oracle.com/cd/E19253-01/819-7060/ldapsetup-1/index.html
[3] Linux 域身份、身份验证和策略指南 | Red Hat Enterprise Linux | 7 | Red Hat Documentation
[4] 5.4. The IdM Web UI | Linux 域身份、身份验证和策略指南 | Red Hat Enterprise Linux | 7 | Red Hat Documentation

Avatar photo

关于 木子

Email: [email protected] 微信:rockylinuxcn QQ: 2306867585
Founder of the Rocky Linux Chinese community, MVP、VMware vExpert、TVP, advocate for cloud native technologies, with over ten years of experience in site reliability engineering (SRE) and the DevOps field. Passionate about Cloud Computing、Microservices、CI&CD、DevOps、Kubernetes, currently dedicated to promoting and implementing Rocky Linux in Chinese-speaking regions.
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


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