当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 构建 Active Directory 运行状况检查工具:第一部分

作者:精品下载站 日期:2024-12-14 13:14:24 浏览:15 分类:玩电脑

构建 Active Directory 运行状况检查工具:第一部分


如果您使用 Active Directory (AD),它可能是您拥有的最重要的系统。如果没有它,用户将无法登录,他们可能无法浏览网页,机器无法通信,财务部门将无法生成最新报告。确保您可以使用运行状况检查脚本来测试 Active Directory!

在本文中,您将了解如何使用 PowerShell 从 AD 收集信息。这将帮助您识别、报告并最终解决与 AD 环境相关的任何问题。

这是由两部分组成的系列的第一部分。在这一部分中,您将了解要检查的内容以及如何构建最终进入 Active Directory 运行状况检查脚本的单独测试。如果您希望立即下载完整的脚本并了解如何构建报告,请随时查看构建 Active Directory 运行状况检查工具[深入]:第二部分。

Active Directory 运行状况是一个广泛的主题

“Active Directory 健康状况”这个术语有很多含义,因此有很多方法可以验证其操作安全性。对于组织而言,仅监控下表中的一项甚至不监控 AD 健康属性的情况并不少见。但这些组织不知道的是,他们每一个都是至关重要的!

Name

描述

Replication

这就是域控制器同步其数据的方式。如果没有它,用户、计算机、DNS 和许多其他属性将不同步。

Connection

拥有良好的连接并打开正确的端口对于 AD 及其客户端的正常运行非常重要。

Event Log

错误和问题迹象有时会显示在事件日志中。

DNS

测试 DNS 和 DNS 服务器对于 Active Directory 的服务发现和通信至关重要。

Duplicate attributes

虽然在数据库中看到重复的属性不会损害 AD,但这可能会给无法登录的用户或无法连接到的服务带来一些麻烦。

您将在本文中了解如何对这些类别执行各种检查。

使用例程进行 Active Directory 健康检查

在 AD 健康方面需要进行很多检查。你可能永远无法全部抓住它们。使用您将在本文中学到的材料,您可以发现发生的大多数错误。但是,如果您没有例程来支持 AD 故障或安全漏洞,那么您将在本文中学习的策略就没用了。

如果您想要一个可靠且有弹性的 Active Directory 环境,请首先问自己以下问题:

  • 我上次进行备份测试是什么时候?
  • 我上次在灾难恢复 (DR) 环境中执行完整林恢复是什么时候?
  • 硬件是否与 AD 服务分离,以便在虚拟机管理程序发生故障时 AD 仍然可以运行?
  • 站点链接是否平衡,以便在主站点出现故障时其他站点可以处理它?
  • 其他站点的域控制器可以处理额外的负载吗?
  • 我是否有域控制器的 Windows Server 2003 或更高版本备份(Microsoft 支持的唯一备份解决方案)?

如果您对其中许多问题的回答是否定的,则应与您的 Microsoft 代表(或 Microsoft 合作伙伴)讨论名为 ADRAP(主动 AD 维护)和 ADRES(Active Directory 灾难恢复培训)的计划。

ADRAP 将对您的 AD 健康、安全和与之相关的日常活动进行精心细致的检查。 ADRES 用于学习和建立围绕 Active Directory 灾难恢复的例程,以防崩溃或违规。

如果您在大型组织中,这两个计划可能非常有价值。

遵循的先决条件

在本文中,您将学习如何使用 PowerShell 和其他一些工具构建 Active Directory 运行状况检查。在您深入了解并想要继续学习之前,请确保满足以下先决条件。

  • 一个或多个 2016 Active Directory 域控制器 (DC)(可能适用于旧版本,但未经测试)
  • 运行脚本的帐户需要是 Domain Admins 组的成员或同等级别的成员。
  • 至少在 DC 上打开 WSMan 和 RPC 端口。如果您不确定,请查看这篇文章,了解如何使用 PowerShell 测试 RPC 端口,并使用 Test-WSMan PowerShell 命令测试 WSMan 远程功能。

运行 DcDiag 命令测试(使用 PowerShell Boost)

Dcdiag 或(域控制器诊断)是 Microsoft 批准的验证 Active Directory 服务的方法。默认情况下,它安装在所有具有 Active Directory 域服务角色的服务器上以及安装了远程服务器管理工具 (RSAT) 包的 Microsoft Windows 10 计算机上。

相关:安装 Active Directory 模块

管理员已经使用 dcdiag 很长时间了,但它有一个很大的缺点:它会创建一份报告,如果出现问题,它不会自动发出信号。

只是为了了解 dcdiag 的广泛性,请查看它可以运行的每组测试以及下面的简要说明。

Test

描述

Advertising

验证定位 DC 的功能是否正常工作以及 DC 是否可以正确地通告自己回来。

CheckSDRefDom

验证分区交叉引用对象中的 SDReferenceDomain 属性是否包含正确的域名。

CheckSecurityError

执行许多不同的测试。默认情况下不执行这组测试。这套测试确保至少一个 KDC 在线、UDP 包不分段、DC 的计算机帐户存在且包含正确的属性和最低 SPN 配置、DC 的计算机对象复制正确且未发生复制或 KCC 错误对于互联合作伙伴

Connectivity

测试与 DC 服务的连接。始终在每次测试之前执行。

CrossRefValidation

验证命名上下文中的 CnNamednsRootNetBiosName 是否正确。

CutOffServers

确保所有 DC 都有用于复制的工作连接对象。

DcPromo

测试推广新 DC 的可能性。默认不执行。

DNS

一系列测试来验证 DNS 服务是否正常工作。

SysVolCheck

读取 SysvolReady 注册表项以验证 SYSVOL 是否已公布。

LocatorCheck

验证 DCLocator 方法是否正确地公布了域必须包含的五种功能。这些功能包括全局编录、PDCEmulator、时间服务器、首选时间服务器和 KDC。

Intersite

检查可能阻止站点间 AD 复制的条件。

KccEvent

检查过去 15 分钟内发生的 KCC 错误。

KnowsOfRoleHolders

测试 FSMO 角色持有者的广告。

MachineAccount

验证 DC 的计算机帐户 OU、UAC、ServerReference 和 SPN。

NCSecDesc

验证所有命名上下文的权限。

ObjectsReplicated

验证 AD 中的关键对象是否是最新的。

OutboundSecureChannels

测试外部信任,默认情况下不运行。

Replications

检查所有 AD 复制对象是否有错误并确保它们没有被禁用。

RidManager

验证可以联系RID Master FSMO 角色并具有有效的 RID 池值。

Services

验证关键服务是否正常工作。

SystemLog

检查过去 60 分钟内 DC 的 Windows 系统事件日志中发生的错误。

Topology

验证 AD 复制拓扑是否完全连接。

VerifyEnterpriseReferences

验证所有 DC 的计算机参考属性。

VerifyReferences

验证 DC 的计算机引用属性。

VerifyReplicas

验证指定的 DC 是否包含它应具有的应用程序分区。

有关 dcdiag 的完整参考,请务必查看 Microsoft 目录服务团队在 Technet 上发布的这篇博客文章。本文从开发人员那里收集了深入的知识,因为它的许多功能可能相当神秘。

使用 DCDIAG 通过 PowerShell 测试 Active Directory

Dcdiag 虽然是一个方便的实用程序,并且是对任何 Active Directory 运行状况检查的一个很好的补充,但它有一个主要缺点 - 输出。输出是老式的,因为它返回一个不容易解析的松散字符串。要将 dcdiag 合并到大型 PowerShell AD 运行状况检查脚本中,您需要将该输出转换为 PowerShell 对象。

通过 Powershell 解析和使用 dcdiag 是将 dcdiag 结果转换为对象的简单方法,然后您可以将其发送到报告、监控系统、测试框架等。

将 PowerShell 和 dcdiag 结合起来的关键是使用 /test: 参数单独运行每个 dcdiag 测试。通过分离这样的测试,可以更容易地区分失败的测试和通过的测试。

请注意,dcdiag 执行查询 DC 事件日志的测试。这些测试返回不同的输出结构,并且应该使用您稍后将学到的其他技术进行解析。

设置自定义 Test-AdHcDcDiag PowerShell 函数

为了节省构建自己的 dcdiag 解析脚本的时间,您可以使用名为 Test-AdHcDcDiag 的自定义 PowerShell 函数。您可以通过此处的 GitHub Gist 下载此函数

Test-AdHCDcDiag 函数执行除 DFSREventFRSEventSystemLog 测试之外的所有 dcdiag 测试。 dcdiag 默认情况下不执行的一些测试可通过应在所有 AD 环境中工作的参数进行。

对于本文,我假设您的一台 DC 上名为 Test-AdHCDcDiag.ps1 的文件中有 Test-DcHcDcDiag 函数。

您可以通过点源在 PowerShell 控制台中使用此函数,如下所示。

PS51> . C:\Path\To\Test-AdhcDcDiag.ps1

如果您不想点源 PowerShell 脚本,可以将代码直接复制并粘贴到 PowerShell 控制台中以获得相同的效果。

运行 Test-AdHcDcDiag PowerShell 函数

一旦该函数可用,您就可以不带参数运行它。然后您应该看到如下所示的输出。这假设您想在域控制器上执行 dcdiag(该函数在幕后调用的实用程序)。

PS51> Test-AdhcDCDiag

....
Source      : dc01
TestName    : DCDiagCheckSecurityError
Pass        : True
Was         : {0, 0}
ShouldBe    : {0, 0}
Category    : DCDIAG
SubCategory : CheckSecurityError
Message     :
Data        : {........................ Test passed}
Tags        : {DCDIAG, CheckSecurityError}
--snip--

但是手动在调用DC上运行该函数太麻烦了。为了防止这种情况,您可以使用 ComputerName 参数提供其他 DC,或者通过管道提供它,如下所示。

PS51> Test-AdhcDCDiag -ComputerName dc02
PS51> "DC01","DC02" | Test-AdhcDCDiag

Active Directory 运行状况检查中的 Test-AdHcDcDiag 功能还允许您通过 Tests 参数显式指定特定测试或通过 ExcludeTests 参数。下面显示了此语法的示例。

# Only running
PS51> Test-AdhcDCDiag -Tests DCPromo,RegisterInDNS

# Excluding
PS51> Test-AdhcDCDiag -ExcludeTests DCPromo

测试 Windows 事件日志中的错误

在事件日志中查找错误是尽早发现潜在问题的一个重要的主动步骤。 Dcdiag 包括查询 Windows 事件日志的测试,但它们的噪音很大,并且会报告误报,例如 DFSR 是否暂停进行备份。

构建您自己的 PowerShell 函数,该函数可以过滤掉噪音,并避免在测试 Active Directory 时处理误报的麻烦。

请注意,最好将域控制器日志发送到可以产生近乎即时警报的第三方日志记录解决方案。毕竟,其中一些事件可能非常严重,需要您迅速采取行动。一个例子是 ESENT 事件 508 错误 - SAN 无法进行故障转移并决定使用几个 DC 时发出的微弱声音。

DFS 复制事件日志中的常见错误

每个 DC 上的 DFSR 服务负责复制包含组策略的 SYSVOL 文件夹。 DFSR 不正常的指标之一是 DFS 复制事件日志中存在错误事件。

任何事件日志错误都值得关注,但仅仅因为存在错误并不意味着它很严重。例如,事件 ID 5014 是完全正常的错误,但前提是在事件中定义了错误 ID 9036(暂停备份)。

Ddciag 不会检查事件中的错误 ID 9036,因此它会产生噪音,并且如果在错误的时刻执行,将始终报告失败。

查找跟踪此特定错误的最可靠方法是使用 PowerShell。您可以使用 Get-EventLogGet-WinEvent cmdlet 读取 DFS 复制日志,并筛选出 ID 为 5014 且在事件的第七个事件中错误 ID 为 9036 的任何事件。替换字符串。您可以在下面看到这样的示例。

PS51> $Events = Get-EventLog -LogName "DFS Replication" -EntryType Error -After (get-date).AddDays(-1)
PS51> $Events | Where-Object {$_.EventId -ne 5014 -and $_.ReplacementStrings[6] -ne 9036}

过滤掉系统事件日志中的常见误报

搜索系统事件日志中的错误是测试 Active Directory 的关键部分,几乎与搜索 DFS 复制事件日志相同。主要区别在于,根据您的环境,需要过滤掉更多内容。

如果系统事件日志中注册了错误事件,您可能需要过滤掉一些警告,以防止报告中出现误报。

  • Netlogon 事件 ID 5722、5723 和 5805(已停用或删除尝试联系域的计算机)
  • KDC 事件 ID 16(如果禁用 DES 加密)
  • KDC 事件 ID 11(重复的服务主体名称)
  • 当 Microsoft 组件尝试在没有适当权限的情况下访问 DCOM 组件时发生的常见安全忽略 DCOM 事件。

您可以通过创建排除每个场景的 PowerShell 脚本块来解释每个误报。您可以在下面看到一个查询系统事件日志中的错误并排除刚刚引用的常见场景的示例。

$Filter = {
    # Filter out computers unable to contact domain because they're removed or disabled
    !($_.Source -eq 'NetLogon' -and $_.eventid -in @(5805,5723, 5722)) -and

    # Filter TGS/TGT events
    !($_.Source -eq 'KDC' -and $_.EventId -in @(16,11)) -and

    # Filter out DCOM errors
    !($_.Source -eq "DCOM" -and $_.EventId -eq 10016)
}

## Assuming this is run on a DC, it queries the system event log for errors excluding all common false positive situations
Get-EventLog -LogName "System" -EntryType Error | Where-Object $Filter

检查重复的 AD 属性

重复的 AD 属性虽然不一定是问题,但在适当的情况下可能会变成一场噩梦。例如,重复的 UPN、邮件或 ProxyAddresses 属性将导致 Azure AD、Office 365 和一般身份验证问题出现错误。重复的属性可能会导致该用户的 AD 属性同步失败。

如果您没有正确测试 Active Directory,重复的 SPN 可能会导致更严重的 Kerberos 问题和与身份验证相关的错误。例如,当用户尝试使用引用特定 SPN 的 Kerberos 进行身份验证时,如果存在重复的 SPN,身份验证将失败。该尝试将失败,因为 Kerberos 仅需要一个 SPN。

加速重复 AD 属性发现

使用 PowerShell,有几种不同的方法可以搜索重复的 AD 属性。您可以使用 Get-ADObject 等 cmdlet 查询 AD,然后使用 Group-Object cmdlet 将属性分组在一起,但还有更好的方法来执行此操作。相反,您可以使用哈希表来加快搜索速度。

要使用此方法:

  • 获取数组中的所有属性
  • 定义一个没有键的哈希表
  • 使用属性名称和存在的实例数填充哈希表键
  • 查找所有大于 1 的哈希表值

以下是 PowerShell 语法示例。

$adAttributeName = 'AttributeNameHere'
$adAttributes = (Get-AdObject -LDAPFilter "$adAttributeName=*" -Properties $adAttributeName).$adAttributeName

$hashtable = @{}

$adAttributes.foreach({ $hashtable[$_]++ })

$hashtable.GetEnumerator().where({ $_.Value -gt 1 }).Key

只需更改 $adAttributeName 变量的值,您就可以快速追踪任何重复的 AD 属性。

常见的 AD 属性重复问题

有一些已知会导致问题的属性:

  • 用户主体名称 (UPN) - 可能会导致 AD、ADFS、证书等的整体身份验证错误)
  • 服务主体名称 (SPN) - 可能导致 Kerberos 身份验证错误
  • 邮件属性 - 可能会导致 Office 365 和 Exchange 中前面提到的问题
  • proxyAddresses 属性 - 可能会给 Office 365 或 Exchange 带来问题,因为它适用于最初拥有 ProxyAddress 的用户,但其他获得该代理地址的用户相同的 ProxyAddress 将无法获得更新

使用上一节中描述的搜索技术,您可以将这些属性插入到下面的脚本中,以查找所有属性的重复值。

$adAttributeNames = 'UserPrincipalName','ServicePrincipalName','mail','ProxyAddresses'

foreach ($adAttrib in $adAttributeNames) {
	$adAttributes = (Get-AdObject -LDAPFilter "$adAttrib=*" -Properties $adAttrib).$adAttrib

	$hashtable = @{}

	$adAttributes.foreach({ $hashtable[$_]++ })

	$hashtable.GetEnumerator().where({ $_.Value -gt 1 }).Key
}

臃肿的用户 Kerberos 令牌

有时,AD 用户帐户的 Kerberos 令牌会变得大于最大令牌大小。这称为“膨胀的 Kerberos 令牌”。 Kerberos 令牌是用户帐户所属的每个组的组合。这些组可以直接分配或从其他组继承。

用户 Kerberos 令牌膨胀的问题通常始于旧版本的 Windows,因为 MaxTokenSize 注册表属性(kerberos 令牌的最大大小)在每个版本中都会增加。您会发现这是较大环境中的常见问题。

查找 Kerberos 最大令牌大小

要查找您环境中的最大令牌大小,您可以在任何 DC 上的注册表中查询 MaxTokenSize 值。您可以在下面看到通过 PowerShell 执行此操作的示例。

PS51> Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters -Name MaxTokenSize

查找跨用户帐户的帐户令牌大小

您可以使用 PowerShell 查找与用户帐户关联的 Kerberos 令牌大小,但这不是一个简单的过程。为此,您只能估计令牌大小。

警告:每个用户帐户查找令牌大小的过程通常需要八到十秒。在此期间,由于使用 LDAP_MATCHING_RULE_IN_CHAIN LDAP 过滤器,它还会使正在查询的 DC 承受很大的负载。此过程尝试递归地获取用户的嵌套组成员身份。

您可以在下面看到一个 PowerShell 代码段,它将查找域管理员组的所有成员的用户帐户令牌大小。如果您想在另一个组上运行此代码段,请更改 $groupName 的值。

下面的示例计算每个用户的大致令牌大小,并输出计算出的令牌大小超过 48000 的每个用户。

## The group name to find user accounts in
$groupName = 'Domain Admins'

## Find distinguished names of all accounts in the group
$UserDNs = (Get-ADGroupMember $groupName).DistinguishedName

## Define an array to store token sizes in
$TokenSizes = @()

Foreach($UserDN in $UserDNs) {
    # Get all nested groups using LDAP_MATCHING_RULE_IN_CHAIN (1.2.840.113556.1.4.1941)
    $Groups = Get-ADGroup -LDAPFilter "(member:1.2.840.113556.1.4.1941:=$UserDN)" -Properties sIDHistory

	## Create an object to output
    $Object = [PSCustomObject]@{
        DistinguishedName = $UserDN
        UserTokenSize = 1200
    }
	
    ## Process each group the user is a part of
    foreach ($Group in $Groups){
        if ($Group.SIDHistory.Count -ge 1){
            # Groups with sidhistory always counts as +40
            $Object.TokenSize = 40
        }
        switch($Group.GroupScope){
            'Global' {$Object.UserTokenSize+=8}
            'Universal' {$Object.UserTokenSize+=8}
            'DomainLocal' {$Object.UserTokenSize+=40}
        }
    }
    $TokenSizes += $Object
}

# Restrict token sizes output to any greater than 48000. The max default token size for 2012R2 is 48000
$TokenSizes | Where-Object {$_.UserTokenSize -gt 48000}

修复臃肿的 Kerberos 令牌

您可以通过几种不同的方法主动阻止过大的 Kerberos 令牌:

  • 从组中删除用户
  • 实行精心设计的群体嵌套策略
  • 将用户帐户添加到域本地组,因为域本地组分配较小部分的令牌
  • 增加 Kerberos 令牌大小

过大或臃肿的 Kerberos 令牌可能很难追踪。您所看到的问题很少与此问题直接相关。但是,您现在应该有一些代码来跟踪此问题并主动修复它们。

寻找漫游客户

缺少子网可能会导致域控制器上的 DCLocator 服务出现许多问题。缺少子网可能会导致客户端选择错误的 DC、DFS 共享以及依赖 AD 站点的任何其他内容。

当子网丢失时,客户端将“漫游”,这意味着他们无法找到与之关联的站点。当计算机找不到站点时,AD 将在 DC 的 netlogon.log 文件中生成一条消息。

如果客户端找不到站点(漫游),它将生成一条带有行 NO_CLIENT_SITE 的日志消息。您可以手动搜索每个 DC 上的每个 netlogon.log 文件,也可以使用下面的 PowerShell 代码段来查找它们。此代码段输出 netlogon.log 文件中记录的所有事件,该文件包含字符串 NO_CLIENT_SITE: ,后跟计算机名称和 IP 地址。

您将在每个 DC 上运行它。

$NetLogonLog = Import-Csv "$env:SystemRoot\Debug\netlogon.log" -Delimiter " " -Header Date,Time,Pid,Domain,Message,ComputerName,IpAddress
$NoClientSite = $NetlogonLog | Where-Object Message -eq "NO_CLIENT_SITE:" | Select ComputerName,IpAddress
$NoClientSite

要更深入地了解此主题(包括用于读取所有 DC 上的所有 netlogon.log 文件的 PowerShell 脚本),请查看没有站点 ATA 的 Active Directory 计算机博客文章。

组策略

组策略或 GPO 是 Active Directory 的重要组成部分,也是我们配置加入域的计算机的方式的一部分。组策略将文件存储在所有 DCs 的 SYSVOL 共享中,并且 SYSVOL 通过 DFSR 进行复制。因此,您已经了解了一些有关组策略健康状况的知识。您已经了解了如何报告SYSVOL复制问题。

GPO 运行状况不仅限于 SYSVOL DC 共享。在测试 Active Directory 时,您可以运行一些其他 AD 运行状况检查,以确保组策略处于最佳状态,例如未链接的 GPO 和存储在 GPO 中的密码。

检查未链接的 GPO

如果 GPO 未链接到组织单位 (OU),则它无效。它只是占用您的 AD 数据库中的空间。如果 GPO 未链接且未用作模板,建议将其删除。

下面您将看到一个 PowerShell 脚本,它以 XML 格式查询 AD 中的所有 GPO,并查找所有未链接到 OU 的 GPO。

[xml]$GPOXmlReport = Get-GPOReport -All -ReportType Xml
($GPOXmlReport.GPOS.GPO | Where-Object {$_.LinksTo -eq $null}).Name

查找包含可解密密码的 GPO

我认为 AD 健康不仅仅是破坏/修复问题和性能。我还认为 AD 健康与 AD 安全有关。包含可解密密码的 GPO 是一个主要的安全风险,应该成为 AD 运行状况检查脚本的一部分。

不幸的是,自从多年前密钥泄露以来,包含密码的组策略首选项已经可以解密。有些人仍然没有意识到这一点,并且是暴露敏感密码的主要风险。

GPO 以 XML 格式存储。您可以通过上一节中使用的命令注意到这一点。您可以在 GPO 首选项中定义密码,然后 AD 将其存储在该 GPO 的 XML 文件中。

当密码存储在 GPO 首选项中时,它会存储在名为 CPassword 的属性中。不幸的是,这对世界来说是一个安全风险,但对您来说幸运的是,您可以使用 PowerShell 读取每个 GPO 的 XML 文件并确定是否正在使用 CPassword XML 属性。

您将在下面找到来自 TechNet 的 PowerShell 脚本的修改版本。在域控制器上运行时,此脚本会读取 SYSVOL 文件夹中的所有 GPO XML 文件,并使用正则表达式搜索 CPassword XML 属性。

强制执行合规性要求,阻止超过 30 亿个被泄露的密码,并通过动态最终用户反馈帮助用户在 Active Directory 中创建更强的密码。立即联系我们了解 Specops 密码政策!

$Path = "C:\Windows\SYSVOL\domain\Policies\"

# Get all GPO XMLs
$XMLs = Get-ChildItem $Path -recurse -Filter *.xml

# GPO's containing cpasswords
$cPasswordGPOs = @()
# Loop through all XMLs and use regex to parse out cpassword
# Return GPO display name if it returns
Foreach($XMLFile in $XMLs){
    $Content = Get-Content -Raw -Path $XMLFile.FullName
    if($Content.Contains("cpassword")){
        [string]$CPassword = [regex]::matches($Content,'(cpassword=).+?(?=\")')
        $CPassword = $CPassword.split('(\")')[1]
        if($CPassword){
            [string]$GPOguid = [regex]::matches($XMLFile.DirectoryName,'(?<=\{).+?(?=\})')
            $GPODetail = Get-GPO -guid $GPOguid
            $GPODetail.DisplayName   
        }
    }
}

继续阅读

在本系列的第一部分中,您学习了一些要监视的 AD 组件以及如何使用 PowerShell 查询这些组件。如果您想继续阅读如何报告和监控您在本文中了解的 Active Directory 运行状况检查测试,请转到第二部分。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯