
1、场景描述
服务端ip:192.168.21.159
客户端ip:192.168.21.137、192.168.21.204
1.1 在服务端的主机上创建普通账号autoops
#登录服务端主机,创建普通账号
useradd -m -s /bin/bash autoops
passwd autoops #设置密码
1.2 设置此账号具有sudo权限
#添加普通用户到wheel组,使其具有sudo权限
gpasswd -a autoops wheel
#验证wheel组
cat /etc/group |grep wheel
id autoops
可以看到autoops用户已经是在wheel组了

#从普通用户autoops登录服务器
执行sudo cp命令验证,已经具有sudo权限

1.3 设置sudo免密权限
#设置sudo免密执行
vi /etc/sudoers #编辑
autoops ALL=(ALL) NOPASSWD: ALL
:wq! #保存退出

现在从autoops登录后执行sudo命令已经不需要再输入密码了
2、设置客户端主机
2.1 创建普通账号autoops
#登录所有客户端主机,分别创建普通账号
useradd -m -s /bin/bash autoops
passwd autoops #设置密码
![]()
2.2 配置客户端主机ssh免密登录服务端主机
#在所有客户端主机上操作
#192.168.21.137、192.168.21.204分别操作
#切换到autoops用户
ssh-keygen #输入命令,按三次回车,会生成私钥和公钥
cd /home/autoops/.ssh #进入目录,会看到生成的私钥和公钥


#拷贝公钥
ssh-copy-id autoops@192.168.21.159 #输入192.168.21.159的autoops密码
现在从192.168.21.137、192.168.21.204分别ssh登录192.168.21.159已经不需要输入密码了
ssh autoops@192.168.21.159
3、根据ip地址限制sudo权限
需求:
1、允许192.168.21.137使用autoops用户ssh登录192.168.21.159,登录之后可以执行sudo命令
2、允许192.168.21.204使用autoops用户ssh登录192.168.21.159,登录之后禁止执行sudo命令,其它操作不受限制
3.1 在服务端主机操作
登录192.168.21.159
#切换到autoops用户
cp ~/.bashrc ~/.bashrc.bak #备份
vi ~/.bashrc #在最后添加下面的代码
# ==================================================================
# Advanced IP Whitelist with CIDR Support for sudo access control
# Author: DevOps
# ==================================================================
# Function: ip_in_cidr <IP> <CIDR>
# Returns 0 if IP is in CIDR, 1 otherwise
ip_in_cidr() {
local ip="$1"
local cidr="$2"
local mask
# Extract net and bits
local net="${cidr%/*}"
local bits="${cidr#*/}"
# Validate bits
if [[ "$bits" -lt 1 || "$bits" -gt 32 ]]; then
return 1
fi
# Convert IP and net to 32-bit integers
IFS=. read -r i1 i2 i3 i4 <<< "$ip"
IFS=. read -r n1 n2 n3 n4 <<< "$net"
local ip_int=$(( (i1 << 24) + (i2 << 16) + (i3 <<
+ i4 ))
local net_int=$(( (n1 << 24) + (n2 << 16) + (n3 <<
+ n4 ))
local mask=$(( (0xFFFFFFFF << (32 - bits)) & 0xFFFFFFFF ))
# Compare network part
if (( (ip_int & mask) == (net_int & mask) )); then
return 0
else
return 1
fi
}
# Main sudo access control
if [ -n "$SSH_CONNECTION" ]; then
CLIENT_IP=$(echo "$SSH_CONNECTION" | cut -d' ' -f1)
# Define whitelist: single IPs and CIDR blocks
ALLOWED_LIST=(
"192.168.21.137"
"172.17.31.222"
"10.103.128.192/27"
)
ALLOWED=false
for item in "${ALLOWED_LIST[@]}"; do
if [[ "$item" == */* ]]; then
# It's a CIDR
if ip_in_cidr "$CLIENT_IP" "$item"; then
ALLOWED=true
break
fi
else
# It's a single IP
if [[ "$CLIENT_IP" == "$item" ]]; then
ALLOWED=true
break
fi
fi
done
if [[ "$ALLOWED" == false ]]; then
sudo() {
echo "错误:您的 IP 地址 $CLIENT_IP 无权执行 sudo 命令" >&2
echo "请联系管理员申请访问权限" >&2
return 1
}
export -f sudo
fi
fi
:wq! #保存退出


3.2 参数说明
1、$SSH_CONNECTION 环境变量
SSH 登录时由 OpenSSH 自动设置,格式为:<客户端IP> <客户端端口> <服务端IP> <服务端端口>
→ cut -d' ' -f1 可准确提取源 IP
2、纯 Bash 实现 CIDR 判断
通过位运算将 IP 和子网掩码转为整数,精确判断是否在网段内
→ 无需依赖 ipcalc、python 等外部工具,兼容所有 Linux 发行版
3、函数覆盖 sudo
在非白名单 IP 的 SSH 会话中,sudo 被重定义为一个报错函数
→ 用户输入 sudo xxx 会直接失败,无法绕过(除非修改 .bashrc)
4、不影响本地任务
cron、systemd、本地 shell 脚本 没有 $SSH_CONNECTION,所以不会触发限制
→ autoops 的全局 sudo 权限依然可用
3.3 使配置文件生效
source ~/.bashrc
4、效果验证
当从非白名单 IP 192.168.21.204 执行 sudo 时,用户将看到:
错误:您的 IP 地址 192.168.21.204 无权执行 sudo 命令。
请联系管理员申请访问权限。

当从白名单 IP 192.168.21.137 执行 sudo 时,一切正常。

#安全加固建议,root权限执行
sudo chattr +i /home/autoops/.bashrc
#如需修改,先执行:
sudo chattr -i /home/autoops/.bashrc
至此,基于源 IP 白名单的 SSH 会话级 sudo 访问控制方案完成。

②190706903
③203744115

