Значи чат-пат нещо се размирисва около това че е много модерно разни хахори да сканират IP ranges, търсейки отворен ssh порт, където някакъв скрипт пробва да брутфорсва акаунти със слаби пароли. Това, което е още по-потресаващо е че това нещо има успеваемост, не знам на какво се дължи този факт, но хората явно няма никога да се научат да си правят по-сложни пароли. След като и аз не съм се научил да го правя, няма какво да мрънкам

'>
Та значи освен гореспоменатия (и най-сигурен според мен начин) същестуват и други решения:
* ssh порта се сменя така че глупавите автоматизирани скенери да не го ловят (тъпа идея, но донякъде работи)
* Слага се някакъв лимит на SYN пакетите с dstport=22 за минута и хостовете, които го надминат, биват REJECT-вани или дропвани. По принцип е идейно решение, с тази разлика че човек, който може да ти прати пакети с spoof-nat source адрес (например от същия етернет сегмент) може да ти сътвори една прекрасна мизерия, карайки те да вдигнеш хиляди правила в iptables. Ако това е рутер дето бута много трафик това може да се окаже малко гадно.
* Port-knocking. Идеята е много добра, но е също така ужасно неудобна. Освен което също до известна степен е податлива на DoS, макар и доста по-трудно.
* host-базиран контрол. Идейно и аз го предпочитам понякога. Обаче понякога все пак ти се налага да се връзваш от неавторизирано място и тогава почваш да се логваш от хост на хост докато стигнеш докъдето трябва.
И въпреки това, тези методи са си успешни. Нооо...аз обаче понеже съм тъп реших да потърся малко по-гъвкав (и податлив на гаври начин). За последното се изискват малко познания по С (малко, щото и аз не съм кой знае какъв програмист). Ииии спокойно, няма да пачваме sshd, въпреки че и там може човек да си даде поле за изява на ТНТМ-ските идиотии

'>
Значи една огромна част от линукс дистрибуциите така или иначе ползват PAM за да автентицират потребители пред дадени услуги. Което е много удобно. Ами какво ще стане ако вземем че си напишем наш си PAM модул, който да прави НАШИ си проверки? В такъв случай вариантите стават доста много

'>
Този случай, който аз ще разгледам сега е доста опростен, значи идеята при мен е един ssh клиент да бъде допуснат САМО ако на неговият хост нещо слухти на определен порт. Това е глупаво, но пък много лесно за реализация. Определено може да се разшири по много други начини (примерно по друг сокет да се обменя допълнителна информация за автентикация, с curl да се дърпа от някъде уеб документ и да се гледа в него за нещо, да се проверява за активационен мейл и кой знае колко още идиотски идеи).
Не мисля да навлизам особено в детайли за PAM модулите - накратко тук:
http://www.linuxdevcenter.com/pub/a/linux/2001/09/27/pamintro.htmlИ по този повод ето го сорса на моя примерен PAM модул:
Примерен код |
#include <security/pam_modules.h> //pam #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <syslog.h> #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h>
#define portno 7000 // change if needed
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags ,int argc , const char **argv ) { int retval; struct sockaddr_in sin; struct hostent *host; int len; int sd; const char *token=NULL;
retval=pam_get_item(pamh,PAM_RHOST,&token); //getrhost
host = gethostbyname(token); // resolve sd = socket(AF_INET, SOCK_STREAM, 0); memcpy(&sin.sin_addr.s_addr, host->h_addr, host->h_length); sin.sin_family = AF_INET; sin.sin_port = htons(portno); // someone listening? if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { syslog(1,"Remote host %s does not listen on port %d\n",token,portno); return PAM_AUTH_ERR; } return PAM_SUCCESS; }
|
Компилираме го и го копираме където му е мястото:
Примерен код |
# cc pmt.c -lpam -shared -o pmt.sо # cp pmt.so /lib/security/
|
И добавяме следния ред в /etc/pam.d/ssh:
Цитат |
auth required pmt.so
|
И това е достатъчно
'>
Оттам нататък може да почваме с пробите:
Цитат |
gat3way:~/pamtest# ssh gat3way@localhost gat3way@localhost's password: (въвеждаме_правилна_парола) Permission denied, please try again. gat3way@localhost's password: ^C gat3way:~/pamtest# tail -n 3 /var/log/auth.log Sep 5 12:55:02 gat3way sshd[27928]: Remote host localhost does not listen on port 7000 Sep 5 12:55:02 gat3way sshd[27928]: pam_unix(ssh:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=localhost user=gat3way Sep 5 12:55:04 gat3way sshd[27928]: Failed password for gat3way from 127.0.0.1 port 37452 ssh2
|
Не иска да ни пусне. Мммм, нека в друга конзола пуснем netcat да ни слухти на порт 7000:
Цитат |
gat3way@gat3way:~$ nc -l -p 7000 |
и да пробваме пак:
Цитат |
gat3way:~/pamtest# ssh gat3way@localhost gat3way@localhost's password: Linux gat3way ..... ^D gat3way:~/pamtest# tail /var/log/auth.log ... Sep 5 12:58:29 gat3way sshd[27988]: Accepted password for gat3way from 127.0.0.1 port 45824 ssh2
|
Воала.
Сега разбира се това горе е прекален прост случай, не е много удобно (щото трябва преди да вържеш ssh трябва да осигуриш нещо да слухти там на клиентската машина), не е практично (ако си зад НАТ кво правим?) и не е чак толкова сигурно (злия хахор може и да забележи, че отсреща някой се опитва да се върже обратно към него).
Но никой не е казал, че нещата трябва да се реализират точно така. Както казах има огромна свобода по отношение на това каква проверка може да се реализира. Може например да се напише да ти иска 2 пъти парола, първият път да каже че е грешна, на втория да те пусне (идейно според мен)...може много неща може.
В тоя ред на мисли приемам идеи
'>