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:


멋져요...
멋지셔요.
잘 지내시죠?!!
휴..... 좀 더
휴.....
좀 더 쉽게해서 초보들을 위해 강좌로 올려주시면 고맙겠습니다.
자료는 저장하자!
저장해서 정리하지 않은 지식은 쓸모가 없다.
댓글 달기