iptables 그리고 포트노킹
글쓴이: woonuk / 작성시간: 토, 2006/06/10 - 12:37오전
한동안 ssh 포트에 대한 무차별 스캐닝이 많아서 결국 포트를 바꿔서 운영하게 되었습니다.
맘편하게 잊고 지내다가 그동안 개념만 이해하고 있던 포트노킹을 iptables 로 설정하는
샘플을 보았습니니다.
http://www.portknocking.org/ 사이트에 다양한 내용들이 있더군요.
아래는 200, 100, 300 포트에 순서대로 접근 시도하는 경우에 해당 IP에 대하여
22번 포트를 오픈하는 iptables 설정입니다.
*mangle :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A INPUT -p tcp -m tcp --dport 200 -m recent --set --name PHASE1 --rsource -j ACCEPT -A INPUT -p tcp -m tcp --dport 100 -m recent --rcheck --seconds 10 --name PHASE1 --rsource -j MARK --set-mark 420 -A INPUT -p tcp -m tcp --dport 300 -m recent --rcheck --seconds 10 --name PHASE2 --rsource -j MARK --set-mark 430 -A INPUT -m mark --mark 420 -m recent --remove --name PHASE1 --rsource -j MARK --set-mark 420 -A INPUT -m mark --mark 420 -m recent --set --name PHASE2 --rsource -j ACCEPT -A INPUT -m mark --mark 430 -m recent --remove --name PHASE2 --rsource -j MARK --set-mark 430 -A INPUT -m mark --mark 430 -m recent --set --name PHASE3 --rsource -j MARK --set-mark 430 -A INPUT -m recent --update --seconds 60 --name PHASE3 --rsource -j MARK --set-mark 47 COMMIT *filter :INPUT ACCEPT [43:5330] :FORWARD DROP [0:0] :OUTPUT ACCEPT [23:3218] -A INPUT -p tcp -m tcp --dport 22 -m mark --mark 47 -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j DROP COMMIT
http://www.gophernet.org/articles/iptables.html 에서 recent 모듈에 해당하는
예제를 참고하였습니다. mark와 recent 모듈에 이해가 부족해서 많은 시행착오를
거쳤습니다 -_-;;
다음은 윈도에서 배치파일로 만들면 편할거 같아서 http://wiki.kldp.org/wiki.php/BeeJNetworkProgramming#s-5.2 client.c를 수정하였습니다.
/* ** Knock.c -- a stream socket client demo for portKnocking ** gcc -o Knock.exe Knock.c -lws2_32 */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <winsock.h> int main(int argc, char *argv[]) { int port[20], i, count; char *errs="ports must be digit number.\n"; char *ports; struct hostent *he; struct sockaddr_in their_addr; // connector's address information WSADATA wsaData; //if this doesn't work //WSAData wsaData; //then try this instead if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0){ fprintf(stderr, "WSAStartup failed.\n"); exit(1); } if (argc < 5 ) { fprintf(stderr,"Usage: Knock.exe hostname [ port1 port2 port3 ... ]\n"); exit(1); } if ( argc >= 5 ) { /* make sure the argument is an integer number */ count = argc - 2; for ( i=2; i<5; i++ ) { ports=argv[i]; while (*ports!='\0') if (!isdigit(*(ports++))) { printf(errs); exit(1); } sscanf(argv[i],"%d",&port[i-2]); } } if ((he=gethostbyname(argv[1])) == NULL) { // get the host info //herror("gethostbyname"); exit(1); } their_addr.sin_family = AF_INET; // host byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct for (i=0; i < count; i++) { portKnock(port[i], their_addr); _sleep(1000); } //WSAClenaup(); return 0; } int portKnock(int dport, struct sockaddr_in their_addr) { int sockfd; if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } their_addr.sin_port = htons(dport); // short, network byte order printf("%d : ",dport); fflush(stdout); if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) { perror("connect"); } closesocket(sockfd); return 0; }
MinGW [ http://sourceforge.net/projects/mingw ] 기본만 설치하고 gcc.exe 로 간단히
컴파일 되더군요.
Forums:
멋져요...
멋지셔요.
잘 지내시죠?!!
휴..... 좀 더
휴.....
좀 더 쉽게해서 초보들을 위해 강좌로 올려주시면 고맙겠습니다.
자료는 저장하자!
저장해서 정리하지 않은 지식은 쓸모가 없다.
댓글 달기