inux-2.6.14 버전 이후로??? 옵션을 추가해줘야 string_match 를 활성화 해 줄 수가있다.
관련 문서
.SS string This modules matches a given string by using some pattern matching strategy. It requires a linux kernel >= 2.6.14.
.TP .BI "--algo " "bm|kmp" Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris) .TP .BI "--from " "offset" Set the offset from which it starts looking for any matching. If not passed, default is 0. .TP .BI "--to " "offset" Set the offset from which it starts looking for any matching. If not passed, default is the packet size. .TP .BI "--string " "pattern" Matches the given pattern. .BI "--hex-string " "pattern" Matches the given pattern in hex notation.
제가 사무실에서 쓸려고 리눅스방화벽을 실험해보고 있습니다. 한가지 문제가 있는데 방화벽안의 192.168.0.0/24 에서 밖의 192.168.1.0/24 으로 통신은 가능한데 방화벽안의 pc끼리는 ping 과 윈도우 작업그룹이 되지 않습니다. 80번 포트는 되더군요. 원래 리눅스 방화벽 초기 설정이 클라이언트들의 통신을 80포트 빼고 모두 차단하나요?
됐습니다. 혹시나 해서 보니 윈도우 방화벽문제 이더군요. 실제로 사용중인 pc들은 델인데 이번에 실험에 쓴 것들은 옛날 해커스 제품이었습니다. 서비스팩 2로 업그레이드 했는데 델하고 방화벽 설정이 다르더군요. 그래서 윈도우 방화벽문제는 아닐 것이라는 편견으로 삽질을 했군요. 정말 감사드립니다.
grep "Failed password for invalid user" /var/log/secure.1 | awk '{ print $13}' | uniq | sed "s/^/all:/" >> /tmp/anonymous_login
{USERID} 부분에는 로그인 하기 위한 ID를 설정한다. 이것을 설정하지 않으면 자기가 로그인 시도를 하다가 실패를 할 경우 콘솔로 가거나 다른IP 장소에서 로그인하지 않으면 안된다.
{LOGINIP} 로그인 장소가 고정아이피이며 특정IP에서는 발생하는 로그인 실패기록은 무시를 할 경우 기록한다. 유동아이피 일 경우는 주의 하도록 한다.
{ print $11} 부분은 접속 실패가 일어 날 경우 접속 거부할 상대방의 IP의 위치
다른 배포판을 위하여 /var/log/secure에 기록되는 내용이 배포판마다 다를 수 있으므로 grep문에 로그를 찾기 위한 부분이나 egrep -v로 로그파일에서 취득하고 싶지 않는 내용을 적거나 awk에 의해 취득해 오기 위한 해당 열의 위치등 설정을 바꾸어 보도록 한다.
- 첫번째의 grep은 존재하는 user id 로 시도를 하려고 할 때 로그인 실패시 IP를 얻기 위한 명령어
- 두번째의 grep은 존재하지 않는 user id 로 시도를 하려고 할 때 로그인 실패시 IP를 얻기 위한 명령어
두번째로는 만들어진 접속 거부 IP와 접속거부 설정 파일과의 머지 작업을 위해 임시 파일을 만든다.
vi /var/log/ch.sh
#!/bin/bash
### ch.sh
# "subst", 파일에서 어떤 패턴을 다른 패턴으로 바꿔주는 스크립트.
# 즉, "subst Smith Jones letter.txt".
ARGS=3
E_BADARGS=65 # 필요한 인자가 빠져있음.
if [ $# -ne "$ARGS" ]
# 스크립트로 넘겨진 인자의 갯수를 확인(항상 이렇게 하세요).
then
echo "사용법: `basename $0` old-pattern new-pattern filename"
exit $E_BADARGS
fi
old_pattern=$1
new_pattern=$2
if [ -f "$3" ]
then
file_name=$3
else
echo "\"$3\" 은 없는 파일입니다."
exit $E_BADARGS
fi
# 여기가 가장 중요한 부분입니다.
sed -e "s/$old_pattern/$new_pattern/g" $file_name
# 's'는 sed의 치환(substitution) 명령어이고,
# /pattern/ 은 주소 매칭을 실행시킵니다.
# 전역(global) 플래그인 "g"를 쓰면 단지 첫번째 일치하는 $old_pattern만
#+ 치환시키지 않고 각 줄에서 일치하는 "모든" $old_pattern을 치환시킵니다.
# 더 자세한 설명은 'sed' 문서를 읽어보세요.
exit 0 # 스크립트의 실행이 성공이라면 0을 리턴.
그리고 마지막으로.... 하나더..
레드헷계열 리눅스는 설치후 아무런설정을 하지 않았다면
root로 ssh를 로그인 가능합니다.
그러므로 root의 직접적인 ssh login은 막고
일반계정으로 접속후 su - root 를 통해 root권한을 획득하여 작업하도록 합니다.
ssh 설정화일을 아래와 같이 열어 PermitRootLogin yes를 no로 변경합니다.
요즘 ssh dictionary attack 이 심합니다. (정확히 말하자면.. ssh brute force attack 이라고 하더군요 ^^) 일전에 제 blog 에서 geoip 를 이용해서 막는 방법을 소개를 했었습니다.
외국에서의 공격, 특히 중국에서의 공격을 막아서인지 현저하게 시도는 줄었지만.. 그래도 3일에 한번꼴로 국낸 IP (특히 대학이나 초등학교 서버에서..) 에서 5000번 이상의 scan 을 하고 지나가는 꼴을 보니 또 오기가 생기기 시작했습니다.
설마 막는 방법에 없겠느냐는 생각에 iptables 의 extension 을 탐색하던 중 ipt_recent extension 을 발견 했습니다. recent extension 은 iptables 의 기본 extension 이므로 따로 빌드할 필요도 없고, seconds 별 hitcount 를 계산할 수 있는 듯 합니다.
아래의 예제를 보죠. (oops.org 에 기본으로 적용한 rule 입니다.)
# ssh buste attack rule%-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSHSCAN%-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update \ --seconds 60 --hitcount 8 --rttl --name SSHSCAN -j LOG --log-prefix SSH_Scan:%-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update \ --seconds 60 --hitcount 8 --rttl --name SSHSCAN -j DROP
1. 처음에 22 번으로 NEW state 의 session 을 SSHSCAN 이라는 이름으로 list 를 만듭니다.
2. 60 초 동안 8 번의 히트를 기록하면, 60초 동안 DROP 합니다.
3. 그리고 SSH_Scan 이라는 prefix 로 logging 을 합니다.
문서들이 영어라서.. 결국에는 습관대로 대충 읽고 반영해서 보자는 식으로 하게 되어서 정확한 정보는 되지 않을 것 같습니다. 정확한 정보를 얻고 싶은 분들은.. 다음의 링크를 참조 하십시오.
전 영어가 딸려서 ^^; 정확한 설명을 알려 주시면 고맙겠습니다. (아 이 귀차니즘의 압박이여.. -_-;)
P.S
안녕 리눅스를 사용하시는 분들은 oops-firewall 을 5.0.0 으로 올리시고 위의 rule 을 user.conf 에 반영하시면 됩니다. 5.0.0 부터는 ALLOWALL 이 user pre command 보다 먼저 실행이 되기 때문에 ALLOWALL 에 등록된 site 는 최소한 이 rule 에 영향을 받지 않습니다.
During 2005, bute force attacks on the ssh (secure shell) service became pretty popular. These attacks are based on a rather simple idea: use an automated program for trying, one after the other, many combinations of standard or frequently used account names and likewise frequently used password (e.g.: guest/guest).
Defence methods
There are a number of methods to defend against such brute force attacks. The following list is intended to give an overview of them, and briefly mention their respective advantages and disadvantages.
Neither in a dictionary, nor trivial variations of trivial passwords (guest1 is just as bad as guest). Using the initials of the words in some sentence is a simple method to have a strong password that is easy to remind (Peter, Paul, and Mary went to school yesterday = PPaMwtsy).
Advantage: Simple
Disadvantages:
Requires enforcement (regular checks of user passwords with tools like e.g. john ("John the Ripper").
Does not reduce the (network, sshd) load caused by the attacks.
If you don't use passwords, but only RSA keys for authentication, a brute force search for a valid password will obviously be useless.
(1) Generate an RSA key with ssh-keygen -t rsa. This will create the files /home/username/.ssh/id_rsa (the private key) and /home/username/.ssh/id_rsa.pub (the public key).
sh$ ssh-keygen -t rsaGenerating public/private rsa key pair.Enter file in which to save the key (/home/username/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/username/.ssh/id_rsa.Your public key has been saved in /home/username/.ssh/id_rsa.pub.The key fingerprint is:32-digit_hexadecimal_fingerprintusername@hostname
(2) On each machine to which where you want to login, copy /home/username/.ssh/id_rsa.pub into /home/username/.ssh/authorized_keys. This file can hold more than one key, so it may be wise to concatenate the freshly generated key.
(3) On each machine from which you want to login, place the file /home/username/.ssh/id_rsa into the directory /home/username/.ssh/.
(4) Disable password-based login by setting 'PasswordAuthentication no' in /etc/ssh/sshd_config, and restart the sshd daemon with /etc/init.d/sshd restart
Advantage: Pretty secure, if done properly
Disadvantages:
Users may use private keys without setting a passphrase to protect them. This implies that getting access to the private key would allow to login to any machine where the corresponding public key is installed.
Non-tech users may need help to generate RSA key for themselves (and for using them).
It is neccessary to carry the private key along to login from another host.
It is possible to set up iptables rules to block ssh attacks. The following ruleset (seen in the blog of Andrew Pollock) will allow at most 3 connections per minute from any host, and will block the host for another minute if this rate is exceeded.
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set \ --name SSH -j ACCEPTiptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 4 --rttl \ --name SSH -j LOG --log-prefix "SSH_brute_force "iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 \ --hitcount 4 --rttl --name SSH -j DROP
For whitelisting, a possible variation (also described by Andrew Pollock) would be:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set \ --name SSHiptables -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH_WHITELISTiptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update \ --seconds 60 --hitcount 4 --rttl --name SSH -j ULOG --ulog-prefix SSH_brute_forceiptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update \ --seconds 60 --hitcount 4 --rttl --name SSH -j DROP
Advantage: Transparent for users
Disadvantages:
Does not distinguish between successful logins and unsuccessful login attempts (i.e. three successful logins within one minute will trigger just like three unsuccessful login attempts).
As pointed out by one reader (L. Hamel), this method requires 'recent' (http://snowman.net/projects/ipt_recent/), an ipfilters patch that may not be in every distro's default kernel. So to use this technique with typical linux distros, you may have to patch the kernel.
It is possible to scan the syslog entries written by the sshd daemon for ongoing attacks, and block the attacker. There are several programs/scripts available that are specifically written for this purpose:
ssdfilter uses iptables for blocking (i.e. it dynamically adds custom firewall rules to block a specific attacker). You need to run sshdfilter instead of sshd. Sshdfilter will then start sshd and monitor its log.
Fail2Ban is a Python script which adds custom firewall rules to block an attacker. It can use the iptables, ipfwadm, or ipfw.
DenyHosts does not use firewall rules to block an attack. Rather, it writes blocking rules to /etc/hosts.deny. Thus, it requires an sshd daemon compiled with support for tcp_wrappers (default on most Linux distributions). Like Fail2Ban, DenyHosts is a Python script.
To find out whether your sshd daemon supports tcp_wrappers, you could use the command ldd /usr/sbin/sshd | grep libwrap. With tcp_wrappers supported you should get a line similar to libwrap.so.0 => /lib/libwrap.so.0 (0xb7f7e000) (numbers may be different). Without tcp_wrappers support, the output will be empty.
Another method to test for tcp_wrappers support would be to add the line sshd: 127.0.0.1 to the file /etc/hosts.deny, and then try to connect to the local ssh server with the command ssh localhost. As you have just blocked localhost, this should fail with the error message ssh_exchange_identification: Connection closed by remote host:
sh$ ssh localhostssh_exchange_identification: Connection closed by remote host
Advantages:
Transparent for users
Can distinguish between unsuccessful login attempts (which are blocked) and successful logins (which are not blocked).
Disadvantages:
Many ssh attacks are fast and short (many connections in a short time). Thus, running a cron script to check the sshd logs for an ongoing attack may be pointless, as it may notice the attack only after it has finished (and the next attack will come from a different machine anyway).
Continuously monitoring the sshd log for an attack requires to run yet another daemon (in the case of sshdfilter, you have to run sshdfilter instead of sshd anyway).
In the preceding section the DenyHosts script was discussed, which scans the sshd logs to detect an attack, and then blocks it with a rule in /etc/hosts.deny. However, it is actually not necessary to scan the logs. It is possible to let the tcp wrapper library start a script whenever a connection is made, and let this script add rules to /etc/hosts.deny or /etc/hosts.allow, if the connecting host should be blocked.
(1) Download the sshblock.sh shell script (PGP signature), and copy it to /usr/local/bin/sshblock.sh (or wherever you like).
(2) Make it executable using the command chmod 755 /usr/local/bin/sshblock.sh
(3) Add the following three lines at the bottom of /etc/hosts.allow
#__START_SSHBLOCK__#__END_SSHBLOCK__sshd : ALL : spawn (/usr/local/bin/sshblock.sh %a)&
This will call the script /usr/local/bin/sshblock.sh for each ssh connection. The script will receive the remote IP address as the first and only argument. The script will write a temporary file /root/hosts.allow, and copy it to /etc/hosts.allow if it differs from that.
Requirements:
The sshd daemon must support tcp_wrappers (see preceding section on methods to test this).
The date command must support the '%s' format specifier to print seconds after the Epoch (use date +%s to test). Both GNU/Linux and FreeBSD date support this.
Configuration: at the top of the script, there are four variables that can be set: DONTBLOCK is the prefix of an address block that you do never want to be blocked (i.e. your own domain). The default is 192.168, which you can safely keep if you have no own domain, as this is a 'private' address block). At most (2) BURST_MAX connections from a host within BURST_TIM seconds are allowed (default: 5 within 60 sec), and blocks are removed after PURGE_TIM seconds (default: 3600 sec). In the script, this looks like:
# your own domain DONTBLOCK=192.168# block host if more than BURST_MAX connections within BURST_TIM secondsBURST_MAX=5BURST_TIM=60# remove block after PURGE_TIM secondsPURGE_TIM=3600
Advantage: Transparent for users
Disadvantages:
Does not distinguish between successful logins and unsuccessful login attempts (i.e. five successful logins within one minute will trigger just like three unsuccessful login attempts).
To remove a block, the script must run, which requires a connection from a non-blocked host (or follow a suggestion by Andreas Rizzi and install a cron job that calls the script with the parameter 127.0.0.0 once per hour).
As pointed out by Imre Veres, another solution to the problem is using knockd, which eliminates the need for having ssh listen on an open port.
Knockd watches predefined patterns in iptables' log, e.g. one hit to port 6356, one hit to port 9356 and two hits to port 3356. I.e. this is equivalent to knocking at a closed door with a "code" that is recognized by knockd. Knockd will then use iptables to open a predefined port (e.g. tcp/22 for sshd) for a predefined time (e.g. one minute). If a ssh session is opened within that time frame, it will remain open, though the ssh port will get closed by knockd after the predefined timeframe expires.
Advantage: Very secure
Disadvantages:
Rather complicated scheme, not suitable for 'mere mortals'.
Requires a suitable program (e.g. knockd-client) for "port knocking" on the client (as well as knockd on the server)