极限首页 业界焦点 软件工程师之路 系统工程师之路 网络工程师之路 软件下载 技术社区
 Linux操作系统的内核编译内
 Linux下设备完全驱动之四
 Linux下设备完全驱动之二
 Linux下设备完全驱动之三
 Linux下设备完全驱动之一
 Linux内核如何从2.4升级到
 开源世界的虚拟机 QEMU
 Linux下软件RAID的实现
 RHEL4内建LVM工具入门
 Cron服务配置详解
 Linux操作系统的内核编译内
 Linux下设备完全驱动之四
 Linux下设备完全驱动之二
 Linux下设备完全驱动之三
 Linux下设备完全驱动之一
 Linux内核如何从2.4升级到
 开源世界的虚拟机 QEMU
 Linux下软件RAID的实现
 RHEL4内建LVM工具入门
 Cron服务配置详解

Shell 中文手册

Python 2.3 中文手册

Python 2.4 中文手册

Mysql 4.x 中文手册

PHP 4.x 中文手册

Apache 2.x 中文手册
更多手册

站内搜索:
当前位置:首页>>系统工程师之路>>管理进阶>>正文
linux SSH 的一些安全小技巧
时间:2005-11-21 作者:netman 来源:netman

 
, 前言

关于 ssh 的好处, 相信不用我多说了吧?
简而言之, 之前的 rpc command telnet 都全可用 ssh 代替
.
比方如下的这些常见功能
:
-
远程登录

ssh user@remote.machine
-
远程执行
ssh user@remote.machine 'command ...'
-
远程粗?
scp user@remote.machine:/remote/path /local/path
scp /local/path
user@remote.machine:/remote/path
- X forward
ssh -X
user@remote.machine
xcommand ...
- Tunnel / Portforward
ssh -L 1234:remote.machine:4321
user@remote.machine
ssh -R 1234:local.machine:4321
user@remote.machine
ssh -L 1234:other.machine:4321
user@remote.machine

至于详细的用法, 我这就不说了. 请读者自行研究吧.
我这里要说的, 是针对 ssh 服务为大家介绍一些安全技巧, 希望大家用得更安心些
.


, 实作


(
实作以 RedHat 9 为范例)

1)
禁止 root 登录

# vi /etc/ssh/sshd_config
PermitRootLogin no


2)
废除密码登录, 强迫使用 RSA 验证(假设 ssh 账户为 user1 )

# vi /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile     .ssh/authorized_keys
PasswordAuthentication no
# service sshd restart
# su - user1
$ mkdir ~/.ssh 2>/dev/null
$ chmod 700 ~/.ssh
$ touch ~/.ssh/authorized_keys
$ chmod 644 ~/.ssh/authorized_keys

--------------------------------------------------
转往 client :
$ ssh-keygen -t rsa
(
按三下 enter 完成﹔不需设密码,除非您会用 ssh-agent
)
$ scp ~/.ssh/id_rsa.pub
user1@server.machine:id_rsa.pub
(
若是 windows client, 可用 puttygen.exe 产生 public key,
然后复制到 server 端后修改之, 使其内容成为单一一行
.)
---------------------------------------------------

回到 server
:
$ cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
$ rm ~/id_rsa.pub
$ exit


3)
限制 su / sudo 名单:

# vi /etc/pam.d/su
auth  required  /lib/security/$ISA/pam_wheel.so use_uid
# visudo
%wheel  ALL=(ALL)   ALL
# gpasswd -a user1 wheel


4)
限制 ssh 使用者名单

# vi /etc/pam.d/sshd
auth       required     pam_listfile.so item=user sense=allow file=/etc/ssh_users onerr=fail
# echo user1 >> /etc/ssh_users


5)
封锁 ssh 联机并改用 web 控管清单

# iptables -I INPUT -p tcp --dport 22 -j DROP
# mkdir /var/www/html/ssh_open
# cat > /var/www/html/ssh_open/.htaccess <<END
AuthName "ssh_open"
AuthUserFile /var/www/html/ssh_open/.htpasswd
AuthType basic
require valid-user
END
# htpasswd -c /var/www/html/ssh_open/.htpasswd user1
(
最好还将 SSL 设起来, 或只限 https 联机更佳, 我这里略过 SSL 设定, 请读者自补.)
(
如需控制联机来源, 那请再补 Allow/Deny 项目, 也请读者自补
.)
# cat > /var/www/html/ssh_open/ssh_open.php <<END
<?
//Set dir path for ip list
$dir_path=".";

//Set filename for ip list
$ip_list="ssh_open.txt";

//Get client ip
$user_ip=$_SERVER['REMOTE_ADDR'];

//allow specifying ip if needed
if (@$_GET['myip']) {
$user_ip=$_GET['myip'];
}

//checking IP format
if ($user_ip==long2ip(ip2long($user_ip))) {

//Put client ip to a file
if(@!($file = fopen("$dir_path/$ip_list","w+")))
{
       echo "Permission denied!!<br>";
       echo "Pls Check your rights to dir $dir_path or file $ip_list";
}
else
{
       fputs($file,"$user_ip");
       fclose($file);
       echo "client ip($user_ip) has put into $dir_path/$ip_list";
}
} else {
echo "Invalid IP format!!<br>ssh_open.txt was not changed.";
}
?>
END
# touch /var/www/html/ssh_open/ssh_open.txt
# chmod 640 /var/www/html/ssh_open/*
# chgrp apache /var/www/html/ssh_open/*
# chmod g+w /var/www/html/ssh_open/ssh_open.txt
# chmod o+t /var/www/html/ssh_open
# service httpd restart
# mkdir /etc/iptables
# cat > /etc/iptables/sshopen.sh <<END
#!/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

list_dir=/var/www/html/ssh_open
list_file=$list_dir/ssh_open.txt
chain_name=ssh_rules
mail_to=root

# clear chain if exits, or create chain.
iptables -L -n | /bin/grep -q "^Chain $chain_name" && {
       iptables -F $chain_name
       true
} || {
       iptables -N $chain_name
       iptables -I INPUT -p tcp --dport 22 -j $chain_name
}

# clear chain when needed
[ "$1" = clear ] && {
       iptables -F $chain_name
       exit 0
}

# do nothing while list is empty
[ -s $list_file ] || exit 1

# add rule
iptables -A $chain_name -p tcp --dport 22 -s $(< $list_file) -j ACCEPT && \
echo "ssh opened to $(< $list_file) on $(date)" | mail -s "sshopen" $mail_to
END
# chmod +x /etc/iptables/sshopen.sh
# echo -e 'sshopen\t\t1234/tcp' >> /etc/services
# cat > /etc/xinetd.d/sshopen <<END
service sshopen
{
       disable = no
       socket_type     = stream
       protocol        = tcp
       wait            = no
       user            = root
       server          = /etc/iptables/sshopen.sh
}
# iptables -I INPUT -p tcp --dport 1234 -j ACCEPT
# cat > /etc/cron.d/sshopen <<END
*/5 * * * *     root    /etc/iptables/sshopen.sh clear
END

---------------------------
转往 client
browser URL 输入:
http://server.machine/ssh_open/ssh_open.php?myip=1.2.3.4
(
若不指定 ?myip=1.2.3.4 则以 client 当时 IP 为准, 若没经 proxy 的话.)
如此, server 端的 ssh_open.txt 文件只有单一记录, 每次盖写
.
接着
:
$ telnet server.machine 1234
然后你有最多 5 分钟时间用 ssh 联机
server !
---------------------------

此步骤的基本构思如下
:
5.1)
sshd firewall 联机全部 block
.
5.2)
然后在 httpd 那设一个 directory, 可设
ssl+htpasswd+allow/deny control,
然后在目录内写一个 php browser ip 记录于一份 .txt 文字文件里
.
视你的转写能力, 你可自动抓取 browser 端的 IP, 也可让 browser 端传入参数来指定
.
文字文件只有单一记录, 每次盖写
.
5.3)
修改 /etc/services , 增加一个新项目( xxx), 并指定一个新 port(
1234)
5.4)
再用 xinetd 监听该 port , 并启动令一只 script, 设定 iptables , step2 的清单里取得 IP, 为之打开 ssh 联机
.
5.5)
crontab 每数分中清理 iptables 关于 ssh 联机的规则. 这并不影响既有联机, 若逾时再连, 则重复上述
.



6)
要是上一步骤没设定, 你或许会担心过多的人来 try 你的 ssh 服务的话
:
# cat > /etc/iptables/sshblock.sh <<END
#!/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

LOG_FILE=/var/log/secure
KEY_WORD="Illegal user"
KEY_WORD1="Failed password for root"
PERM_LIST=/etc/firewall/bad.list.perm
LIMIT=5
MAIL_TO=root
IPT_SAV="$(iptables-save)"
bad_list=$(egrep "$KEY_WORD" $LOG_FILE | awk '{print $NF}' | xargs)
bad_list1=$(egrep "$KEY_WORD1" $LOG_FILE | awk '{print $11}' | xargs)
bad_list="$bad_list $bad_list1"

for i in $(echo -e "${bad_list// /\n}" | sort -u)
do
       hit=$(echo $bad_list | egrep -o "$i" | wc -l)
       [ "$hit" -ge "$LIMIT" ] && {
               echo "$IPT_SAV" | grep -q "$i .*-j DROP" || {
                       echo -e "\n$i was dropped on $(date)\n" | mail -s "DROP by ${0##*/}: $i" $MAIL_TO
                       iptables -I INPUT -s $i -j DROP
               }
               egrep -q "^$i$" $PERM_LIST || echo $i >> $PERM_LIST
       }
done
END
# chmod +x /etc/firewall/sshblock.sh
# cat >> /etc/hosts.allow <<END
sshd: ALL: spawn ( /etc/firewall/sshblock.sh )& : ALLOW
END

这样, 那些乱 try SSH 的家伙, 顶多能试 5 (LIMIT 可调整), 然后就给 BLOCK 掉了.
此外, PERM_LIST ip, 也可提供给 iptables 的初始 script , 来个永久性封闭
:
for i in $(< $PERM_LIST)
do
       /sbin/iptables -I INPUT -s $i -j DROP
done  

7)
还有, 你想知道有哪些人对你做 full range port scan 的话:

# iptables -I INPUT -p tcp --dport 79 -j ACCEPT
cat > /etc/xinetd.d/finger <<END
service finger
{
       socket_type     = stream
       wait            = no
       user            = nobody
       server          = /usr/sbin/in.fingerd
       disable         = no
}
END
# cat >> /etc/hosts.allow <<END
in.fingerd: ALL : spawn ( echo -e "\nWARNING %a was trying finger.\n$(date)" | mail -s "finger from %a" root ) & : DENY
END

这里, 我只是设为发信给 root.
事实上, 你可修改为起动 firewall %a 这个传回值给 ban 掉也行
.
不过, 对方要是有选择性的做 port scan , 没扫到 finger 的话, 那当然就没用了
...


, 结语


security
有蛮多挺好玩的小技巧, 有空再跟大家做分享... ^_^
推荐】【 】【关闭


关于极限 | 站内地图 | 意见反馈 | 广告服务 | 数据服务 | 联系我们
本站所刊登的文章,技术资料,软件均整理于网络资源或本站原创,转载请务必联系原作者或本站。
Copyright ? 2001-2004 UPLinux.com All Rights Reserved.
本站唯一联系信箱:
京ICP备05010519