我们正在努力在办公室内实现零信任安全模型,服务器由 WireGuard VPN 保护。我们已经使用 WireGuard 进行远程访问,因此这是确保所有网络流量加密的最简单方法。WireGuard 为每个用户保证一个特定的 IP 地址。
我们希望使用用户名和 IP 地址来验证文件服务器的访问权限,以防止在发生入侵时发生横向移动。我们使用 Samba 4.13 和简单的默认设置passdb backend = tdbsam
(无域控制器)。
我希望使用 PAM 来提供一个简单的解决方案,但尽管默认配置文件仍然包含auth
,但我读到它不受支持(Samba 使用质询-响应身份验证,这不是 PAM 方式)。当我添加auth required pam_rhosts.so
到时/etc/pam.d/samba
,我的身份验证能力没有任何变化。将其添加到account
或session
部分会导致身份验证失败,即使是从授权 IP 地址。
我能想到的其他解决方案是修改源代码或运行 Active Directory 域控制器,但这些似乎是一项更大的实施和维护工作。应用程序防火墙可能也有效,但我不知道有什么可以检查 Samba 流量。
有没有简单的方法可以将此用户-主机对限制(或一般的 MFA)添加到 Samba 4?
- 编辑 -
该/etc/pam.d/samba
配置显然有一定的效果,因为在该部分的任何行中添加“调试”选项auth
都会提供如下调试日志记录,尽管额外的required
行不会对身份验证的结果产生影响:
[2022/11/10 15:56:56.258835, 3] ../../auth/ntlmssp/ntlmssp_server.c:509(ntlmssp_server_preauth)
Got user=[username] domain=[FILESERVER] workstation=[COMPUTER-NAME] len1=24 len2=190
[2022/11/10 15:56:56.258932, 3] ../../source3/auth/auth.c:200(auth_check_ntlm_password)
check_ntlm_password: Checking password for unmapped user [FILESERVER]\[username]@[COMPUTER-NAME] with the new password interface
[2022/11/10 15:56:56.258959, 3] ../../source3/auth/auth.c:203(auth_check_ntlm_password)
check_ntlm_password: mapped user is: [FILESERVER]\[username]@[COMPUTER-NAME]
[2022/11/10 15:56:56.259651, 4] ../../source3/auth/check_samsec.c:183(sam_account_ok)
sam_account_ok: Checking SMB password for user username
[2022/11/10 15:56:56.262124, 3] ../../source3/auth/auth.c:267(auth_check_ntlm_password)
auth_check_ntlm_password: sam_ignoredomain authentication for user [username] succeeded
[2022/11/10 15:56:56.262230, 4] ../../source3/auth/pampass.c:485(smb_pam_start)
smb_pam_start: PAM: Init user: username
[2022/11/10 15:56:56.267184, 4] ../../source3/auth/pampass.c:494(smb_pam_start)
smb_pam_start: PAM: setting rhost to: 10.1.2.3
[2022/11/10 15:56:56.267246, 4] ../../source3/auth/pampass.c:503(smb_pam_start)
smb_pam_start: PAM: setting tty
[2022/11/10 15:56:56.267285, 4] ../../source3/auth/pampass.c:511(smb_pam_start)
smb_pam_start: PAM: Init passed for user: username
[2022/11/10 15:56:56.267323, 4] ../../source3/auth/pampass.c:569(smb_pam_account)
smb_pam_account: PAM: Account Management for User: username
[2022/11/10 15:56:56.267907, 4] ../../source3/auth/pampass.c:588(smb_pam_account)
smb_pam_account: PAM: Account OK for User: username
[2022/11/10 15:56:56.268550, 4] ../../source3/auth/pampass.c:467(smb_pam_end)
smb_pam_end: PAM: PAM_END OK.
[2022/11/10 15:56:56.268641, 2] ../../source3/auth/auth.c:323(auth_check_ntlm_password)
check_ntlm_password: authentication for user [username] -> [username] -> [username] succeeded
答案1
我对这个特定主题不太热衷,但添加后auth required pam_rhosts.so
,您确实创建了相应的~/.rhosts
文件,对吗?
此链接说 rhosts 文件需要指定hostname [username]
允许的对,我假设 ip 地址可以代替主机名同样有效。
您是否可以分享一些特定的日志消息(当然,如果需要的话,可以删除),以便提供更多见解?
编辑- 不知道这是否会起作用,但你可以尝试网络组。
我不确定设置这些的要求或程序,或者是否像创建和填充文件一样简单/etc/netgroup
。
然后根据手册页中的示例成功时,似乎您可以为(主机,用户)对创建网络组,我想象它看起来像这样:
sambang (alicepc, alice) (bobpc, bob) (charliepc, charlie)
并将此模块添加到您的 samba 身份验证,以使 pam 身份验证在 (主机,用户) 对位于网络组中时成功,例如:
auth required pam_succeed_if.so audit user innetgr netgroup sambang
我可能会更换审计和调试直到它能够工作(假设它可以工作)。
答案2
Samba 的每个 IP/子网文件的 ACL 是否/etc/hosts.allow
足以/etc/hosts.deny
限制用户的共享挂载?
编辑:另外,这里是针对漫游主文件夹的 PAM 模块的答案。也许它与您的用例相同?
FWIW,我会尝试一下Hashicorp 的边界寻求 0 信任解决方案。
答案3
我决定使用 来监控用户会话smbstatus
。这不会在登录时立即发生,因此它不会阻止某人登录,但它会在几秒钟内终止无效会话。这不是一个完美的解决方案,但在我们的例子中应该足够了。
以下是我在 PHP 中实现的方法:
#!/usr/bin/php
<?php
/**
@file blockInvalidSambaUserHosts.php
Block invalid user-host pairs from using Samba.
Run as a root service.
Configure valid pairs in /etc/samba/validUserHosts.conf with lines like:
alice 10.1.0.100
bob 10.1.0.101,10.2.0.88
**/
$STATUS_COMMAND = <<< 'END'
smbstatus -p | awk '/SMB3/{print $1" "$2" "$4}'
END;
$configFile = '/etc/samba/validUserHosts.conf';
if (!file_exists($configFile)) file_put_contents($configFile,'');
list($configTime,$validUserHosts) = getConfig($configFile);
while (true) {
$connections = explode("\n",trim(shell_exec($STATUS_COMMAND)));
foreach ($connections as $c) {
if (!$c) continue;
list($pid,$uname,$ip) = explode(' ',$c);
if (!isset($validUserHosts[$uname])) $msg = "Invalid user $uname.";
elseif (!in_array($ip,$validUserHosts[$uname])) $msg = "Invalid address $ip for user $uname.";
else continue;
error_log($msg);
killProcess($ip);
blockIPAddress($ip,$uname);
//notify($ip,$uname);
}
sleep(10);
// Reload config if it has been modified
if (filemtime($configFile) > $configTime) {
list($configTime,$validUserHosts) = getConfig($configFile);
}
}
// Immediately stop any operations in progress
function killProcess(string $ip): void {
shell_exec("kill -9 $ip");
error_log("Killed smbd process for $ip.");
}
// Immediately block further traffic
function blockIPAddress(string $ip, string $uname): void {
shell_exec("iptables -I INPUT -s $ip -j DROP -m comment --comment '$uname@$ip not valid for Samba'");
error_log("All traffic from $ip is now blocked.");
}
function getConfig($configFile) {
$utime = filemtime($configFile);
$lines = file($configFile);
$validUserHosts = [];
foreach ($lines as $line) {
list($uname,$hosts) = explode(' ',rtrim($line));
$validUserHosts[$uname] = explode(',',$hosts);
}
return [$utime,$validUserHosts];
}
使用如下的 systemd 配置:
# @file blockInvalidSambaUserHosts.service
# @version 1.0.0
[Unit]
Description=Block invalid user-host pairs from using Samba
After=smbd.service
[Service]
Type=simple
ExecStart=/root/blockInvalidSambaUserHosts.php
StandardOutput=append:/var/log/sambaUserHostBlocks.log
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target