Samba 审计跟踪日志
我们 Northrop Grumman 公司最近决定用运行 Samba 的 Linux 服务器替换我们网络中的一台 Microsoft Windows 2000 服务器。用 Linux 替换 Windows 服务器的主要动机是:
Windows 和 Linux 用户使用通用的用户名和密码。
使用 NFS 和 Samba 导出常用共享目录和文件。
允许软件开发人员自由选择他们的开发环境。
Windows 2000 服务器和客户端无需额外的许可费用。
集中化和更清晰的审计跟踪。
更安全的计算环境。
可以根据需要安排软件升级,而不是由外部软件供应商决定。
除了将 Samba 配置为主要域控制器之外,还对 Samba 源代码进行了修改,以满足我们网络的安全要求。本文简要介绍了如何安装和配置 Samba,然后详细解释了如何修改 Samba 源代码以生成审计跟踪所需的日志条目。
我们的网络必须配置为满足公司和客户关于安全性的要求。在必须满足的各种安全要求中,管理员需要能够审计网络上的活动。为这些审计收集和记录的必要信息称为审计跟踪,包括以下信息:成功登录、注销、失败登录和密码更改。
大多数操作系统都会生成包含此信息的日志文件,但这些信息可能分散在许多不同的文件中,并且包含比必要信息更多的信息。我们还希望集中这些信息,以便网络管理员不必检查网络上每台计算机的日志。配置正确后,Windows 2000 服务器会记录连接到网络的所有计算机的上述信息,此外还会报告大量无关信息。这些额外的信息使安全审计时间更长、更容易出错,并且在存档时也会占用大量磁盘空间。
为了使用 Linux 和 Samba 作为 Windows 2000 客户端的主要域服务器,Samba 必须复制 Windows 2000 服务器的日志记录功能。一旦 Samba 为网络配置好,似乎满足日志记录要求的唯一方法是修改 Samba 源代码。修改源代码的另一个好处是能够仅将必要的信息记录在日志文件中。如果 Samba 是闭源的专有产品,则不可能用 Samba 替换 Windows 2000 服务器。
Linux 服务器最初搭载 Red Hat 8.0,并且已安装 Samba。第一步是从网站 www.samba.org 下载 Samba 2.2.8a 的 tar 压缩版本。下载完成后,以 root 用户身份运行以下命令安装 Samba
tar cvfz samba-2.2.8a.tar.gz cd samba-2.2.8a/source ./configure make make install
Samba 可执行文件 smbd 和 nmbd 安装在 /usr/local/samba/bin 目录下。Red Hat 安装程序已将这些可执行文件放置在 /sbin 目录下。使用新创建的 Samba 可执行文件需要更改 Samba 启动脚本 /etc/init.d/samba。应首先通过运行以下命令停止当前的 Samba 守护程序/etc/init.d/samba stop.
然后编辑 /etc/init.d/samba 文件,以便将启动 smbd 和 nmbd 的命令从/sbin/smbd -D更改为/usr/local/samba/bin/smbd -D和/sbin/nmbd -D更改为/usr/local/samba/bin/nmbd -D。然后使用以下命令启动新的守护程序/etc/init.d/samba start.
新的守护程序成功安装后,需要通过在 smb.conf 文件中设置参数来配置 Samba。对于 2.2.8a 发行版,此文件的默认位置是 /etc/samba。smb.conf 文件由方括号表示的部分组成,每个部分命名一个共享或服务。以下示例显示了在 global 部分下设置的一些参数值,以创建 Windows 客户端的主要域控制器
[global] netbios name = SambaServer workgroup = NETDOMAIN domain master = yes local master = yes preferred master =yes os level = 65
为了验证网络上的用户身份,还需要在 global 部分下设置以下参数
encrypt passwords = yes security = user domain logons = yes
最后,对于 Windows 2000 客户端,还需要设置域管理员组和添加用户脚本全局参数
domain admin group = root add user script = /usr/sbin/useradd -d /dev/null \ -g 100 -s /bin/false -M %u
通过添加新部分来创建 Window 客户端的公共和私有共享。
公共
[share] path = /home/share read only = no browseable = yes guest ok = no create mode = 0770 comment = Shared Folder hide dot files = yes
私有
[homes] path = /home/%u read only = no browseable = no guest ok = no map archive = yes create mode = 0750 comment = Home Directories hide dot files = yes
要验证 smb.conf 文件中的参数是否正确,或调试配置问题,请使用 testparm 命令。对于调试 Samba 的一般问题,/var/log/samba 目录下的日志文件 log.smbd 和 log.nmbd 非常有价值。smb.conf 文件 global 部分中的参数 log level 确定 Samba 写入日志文件的详细信息量,级别 0 是最通用的,级别 10 是最详细的。每个日志记录级别都包含来自该级别的消息,以及低于它的日志记录消息。例如,日志记录级别为 5 包含来自级别 5 的消息,以及来自级别 0 到 4 的消息。
清单 1 是 log.smbd 文件中的示例。日志文件中典型条目的第一行包含事件发生的日期和时间、源文件名、函数名以及生成消息的行号。第二行包含发生的动作、域和客户端名称以及描述日志记录事件的简短消息。在本文的后面,我们将检查这些消息是如何在 Samba 源代码中生成的。
清单 1. 来自 /var/log/samba/log.smbd 的日志条目
[2003/11/25 17:13:12, 0] smbd/server.c:main(791) smbd version 2.2.8a started. Copyright Andrew Tridgell and the \ Samba Team 1992-2002 [2003/11/25 17:17:32, 0] \ rpc_server/srv_netlog_nt.c:_net_sam_logon(643) Logon . Domain:[NETDOMAIN].\ HostName:[192.168.0.15]. \ User:[john]. FAILED No Such User [2003/11/25 17:17:55, 0] \ rpc_server/srv_netlog_nt.c:_net_sam_logon(665) Logon . Domain:[NETDOMAIN]. \ HostName:[192.168.0.15]. \ User:[bill]. FAILED Incorrect Password [2003/11/25 17:18:33, 0] \ rpc_server/srv_netlog_nt.c:_net_sam_logon(691) Logon . Domain:[NETDOMAIN]. \ HostName:[192.168.0.15] \ User:[bill] Successfully Logged On [2003/11/25 17:19:34, 0] \ smbd/chgpasswd.c:check_oem_password(836) check_oem_password: incorrect password length \ (262218674) for user bill. [2003/11/25 17:19:46, 0] \ smbd/chgpasswd.c:chgpasswd(474) Password Change: user bill, \ New password is shorter than minimum password \ length = 8 [2003/11/25 17:21:29, 0] \ smbd/chgpasswd.c:chat_with_program(450) Password Change . User:[bill] \ Password Successfully Changed [2003/11/25 17:16:58, 0] \ smbd/service.c:close_cnum(680) clientPC (192.168.0.15) \ closed connection to service bill
可以通过运行以下命令将用户添加到域中smbpasswd -a 用户名以 root 用户身份并设置用户密码。密码存储在 /etc/samba/private/smbpasswd 文件中。也可以使用以下命令禁用用户smbpasswd -d并通过运行以下命令启用用户smbpasswd -e.
有关为 Windows 2000 客户端配置 Samba 和理解 SMB 协议的更多详细信息,O'Reilly 的 使用 Samba,第二版,作者是 Jay Ts、Robert Eckstein 和 David Collier-Brown,是一本极好的参考书。
网络配置完成并正常工作后,下一步是在 log.smbd 文件中记录审计跟踪所需的必要信息。最初,尝试通过在 smb.conf 文件中设置各种日志记录级别,并通过执行以下命令重新启动 Samba 守护程序来实现这一点/etc/init.d/samba restart然后分析日志文件的输出,同时在 Windows 2000 客户端上执行各种任务。不幸的是,无论日志级别如何,都没有记录任何所需的信息。此时,很明显需要修改源代码才能生成日志条目。
Samba 源代码位于 samba-2.2.8a/source 目录中,是日志消息中文件名的根目录。清单 1 中的第一个条目显示文件为smbd/server.c:main(791)。通过检查 samba-2.2.8a/source/smbd/server.c 文件中的第 791 行,您可以看到 DEBUG 宏用于生成日志消息。DEBUG 宏的语法是
DEBUG(log_level, "string", arguments);
第二个和第三个参数的格式类似于 printf 函数。自定义 DEBUG 语句的示例如清单 2 到清单 4 所示。
清单 2. 添加到 source/rpc_server/srv_netlog_nt.c 的 DEBUG 调用
632 /* get the account information */ 633 pdb_init_sam(&sampass); 634 become_root(); 635 ret = pdb_getsampwnam(sampass, nt_username); 636 unbecome_root(); 637 638 639 if (!ret) 640 { 641 pdb_free_sam(sampass); 642 // ESK 631 /* checks for failed users */ 643 DEBUG(0,("Logon . Domain:[%s]. HostName: \ [%s]. User:[%s]. FAILED No Such User \n", lp_workgroup(), client_addr(), nt_username)); 644 return NT_STATUS_NO_SUCH_USER; 645 } 646 647 acct_ctrl = pdb_get_acct_ctrl(sampass); 630 map_username(nt_username); . . . 663 /* Check for failed password */ 664 if (!NT_STATUS_IS_OK(status)) { 665 DEBUG(0,("Logon . Domain:[%s]. HostName: \ [%s]. User:[%s]. FAILED Incorrect Password \n", lp_workgroup(), client_addr(), nt_username)); 666 pdb_free_sam(sampass); 667 return status; 668 } . . . 669 /* Check PAM Password */ 670 #ifdef WITH_PAM 671 become_root(); 672 status = smb_pam_accountcheck(pdb_get_username(sampass)); 673 unbecome_root(); 674 if (!NT_STATUS_IS_OK(status)) { 675 pdb_free_sam(sampass); 676 DEBUG(0,("Logon . Domain:[%s]. HostName: \ [%s]. User:[%s]. FAILED Incorrect Password \n", lp_workgroup(), client_addr(), nt_username)); 677 return status; 678 } 679 #endif . . . 690 /* Makes it to this point you have successfully logged on */ 691 DEBUG(0,("Logon . Domain:[%s]. HostName: \ [%s] User:[%s] Successfully Logged On\n", lp_workgroup(), client_addr(), nt_username));
清单 3. 添加到 source/smbd/service.c 的 DEBUG 调用
675 // ESK 676 if(strcmp(lp_servicename(SNUM(conn)), \ "share") && 677 strcmp(lp_servicename(SNUM(conn)), \ "profiles") && 678 strcmp(lp_servicename(SNUM(conn)),\ "netlogon") && 679 strcmp(lp_servicename(SNUM(conn)), "IPC$")){ 680 DEBUG(0, ("%s (%s) closed connection to \ service %s\n", 681 remote_machine,conn->client_address, 682 lp_servicename(SNUM(conn)))); 683 }
清单 4. 添加到 source/smbd/chgpasswd.c 的 DEBUG 调用
447 448 /* Logs Password Change */ 449 if (chstat) 450 DEBUG(0, ("Password Change . User:[%s] \ %sPassword Successfully Changed\n", 451 name, (chstat ? "" : "un"))); 452 return (chstat); 453 }
创建自定义日志消息需要在代码的适当部分插入 DEBUG 宏,并填写正确的参数和消息。插入 DEBUG 语句后,需要通过在 samba-2.2.a/source 目录中执行以下命令来重新构建 Samba 可执行文件make install使用以下命令重新启动守护程序/etc/init.d/samba restart。现在添加到 Samba 源文件中的任何新日志消息都应出现在日志文件中。
确定 DEBUG 语句应放置在代码中的哪个位置可能需要在 smb.conf 文件中设置各种日志级别。日志文件的输出可以帮助缩小应检查哪些源文件以获取特定信息。使用 printf 语句也可能有助于确定应记录哪些变量以及制定最终的日志消息。如果您计划使用 printf 语句,则应在不使用 -D 选项的情况下执行 smbd 和 nmbd,方法是使用以下命令停止守护程序/etc/init.d/samba stop并执行/usr/local/samba/bin/smbd和/usr/local/samba/bin/nmbd在命令行上。然后 printf 语句将定向到标准输出并显示在控制台上。
清单 2 到清单 4 显示了添加到 Samba 源代码的自定义 DEBUG 语句。清单 2 显示了添加到 source/rpc_server/srv_netlog_nt.c 文件的 DEBUG 语句,用于报告失败和成功的网络登录。第一个 DEBUG 语句报告未知用户尝试登录网络的时间,第二个 DEBUG 语句记录不正确的密码。对于使用 PAM 安装 Samba 的情况,添加了额外的 DEBUG 语句。最后的 DEBUG 语句记录成功登录网络。通过检查清单 1 中的日志输出,您应该看到每个 DEBUG 语句与生成的日志条目之间存在直接对应关系。
清单 3 显示了添加到 source/smbd/service.c 文件的 DEBUG 语句,用于在用户关闭用户共享时捕获用户注销系统的时间。不幸的是,这是一个不可靠的检查,因为用户总是在会话期间删除共享。在用户注销网络和记录删除的共享之间也存在短暂的延迟。确定用户何时注销网络需要检查在上次用户共享被删除后对计算机的任何登录,或者检查计算机是否仍被用户锁定。
一旦 Samba 记录了所需的信息,您可能需要通过删除不必要的条目来清理日志文件。这可以通过将所需 DEBUG 语句的日志级别设置为 0,并将其他 DEBUG 语句的日志级别设置为 1 或更高来实现。然后应将 smb.conf 文件中的日志级别参数设置为 0。Samba 的日志记录功能通过提供 DEBUG 语句的确切位置,可以轻松跟踪不需要的日志条目。与 Windows 2000 服务器生成的日志文件等杂乱的日志文件相比,清理 log.smbd 使审计更容易且更不容易出错。
更新密码时,系统要求规定密码必须至少为八个字符长,并且必须记录密码更改。此外,我们还希望在 Windows 和 Linux 之间同步密码,以便用户在这两个系统上都有通用的登录名。
对于第一个要求,source/include/local.h 中第 175 行的 define 语句更改为#define MINPASSWDLENGTH 8。为了确保此更改在所有必要的源文件中都得到捕获,make clean应在源目录中执行,然后再执行make install.
。用于验证和更新密码更改的源代码位于文件 source/smbd/chgpasswd.c 中。清单 4 显示了添加到 chat_with_program 函数末尾的 DEBUG 语句,用于记录用户何时成功更改密码。除了添加记录成功密码更改的功能外,还会记录失败的密码更新。记录失败的密码更改是因为无论密码更新失败的原因是什么,都会向用户返回以下消息
The User name or old password is incorrect. Letters in passwords must be typed using the correct case. Make sure the Caps Lock is not accidentally on.
这些日志消息可以帮助沮丧的用户确定他们为什么无法更新密码。但是,访问这些日志消息需要系统管理员的协助。清单 1 中的日志条目 5 和 6 提供了用户 bill 无法成功更改其密码的两个示例。
为了在 Samba 和 Linux 系统密码之间同步密码,请在 smb.conf 文件中的 global 部分下设置以下字段
[global] unix password sync = yes pam password change = yes passwd program = /usr/bin/passwd passwd chat =*New*password* %n\n *new*password* ↪%n\n *successfully*
对于大多数系统,passwd chat字段不需要设置,因为默认设置可以正常工作。如果 passwd chat 字段确实需要设置,则语法应与 passwd 命令的输入和输出紧密相随。密码聊天的语法是 * 表示任何字符,%n 表示新密码;空格表示新行,当需要用户输入时使用 \n。为了获得进一步的调试帮助,请将日志级别设置为 101,并将字段passwd chat debug设置为 smb.conf 文件 global 部分中的 yes。作为最后的手段,可以在 chpasswd.c 文件中的函数 chat_with_program 中使用 printf 和 DEBUG 语句来帮助调试问题。
上面提到的一些当前问题,例如在用户未能更新密码时显示更有意义的错误消息,以及更精确地确定用户何时注销网络的方法,都需要解决。还应添加其他功能,例如在连续五次登录尝试失败后锁定用户,以及防止用户重复使用之前的五个密码。使用 LDAP 用于 Linux 和 Windows 客户端也值得研究。
Edward Kablaoui (eskablaoui@yahoo.com) 目前是 Northrop Grumman 的一名软件工程师。他与妻子 Nancy 住在马里兰州。