/***************************************************************************** * File: knock.c * Date: 2006-Apr-29 3:14:27 PM EST * Original Authors: Jason Galens and Pat Wilbur * Last Modified:2006-Apr-30 11:23:05 PM EST * * Description: * * Port knocking daemon that authenticates clients and adds rules to iptables. * * * Notice: * * To be used with knock.c. Copying and distributing this file is permitted as * long as it is packaged with knock.c, and all this information here at the top * of the file, including authors' names, authors' e-mail addresses, the * description, the notice, and the thank you messages are all intact. In other * words, do not touch the area between the stars. If you wish to contribute, * please e-mail one of us! * * libpcap implementation based on the BEST EVER libpcap packet capture tutorial * by Martin Casado. That tutorial may be found at: * http://www.cet.nau.edu/~mc8/Socket/Tutorials/section1.html * * Thank you, Mr. Casado. * ******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define KEY_LEN 16 #define BUF_LEN 256 #define N_PACKETS 16 #define N_PORTS 65536 /* globals */ int sock, length, n; struct sockaddr_in server, from; struct hostent *hp; /* functions */ void error(char *); void send_packet(unsigned short port); void crypt(const unsigned char* buffer, int buf_size, const unsigned char* key, int key_len, unsigned char* ret); int main(int argc, char **argv) { if (argc != 4) { printf("Usage: %s server port username\n", argv[0]); return 0; } srand(time(NULL)); unsigned char knock_buffer[BUF_LEN]; int knock_len, i; bzero(knock_buffer,BUF_LEN); char hostn[BUF_LEN]; struct hostent *hostIP; unsigned short port = (unsigned short)atoi(argv[2]); unsigned char key[KEY_LEN]; // create socket sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) error("socket"); // set destination server.sin_family = AF_INET; hp = gethostbyname(argv[1]); if (hp == 0) error("Unknown host"); bcopy((char *)hp->h_addr, (char *)&server.sin_addr, hp->h_length); length=sizeof(struct sockaddr_in); //send_packet(atoi(argv[2])); if((gethostname(hostn, sizeof(hostn))) != 0) { error("No IP foind"); } hostIP = gethostbyname(hostn); /* fill the buffer with the information in the right order */ knock_buffer[0] = hostIP->h_addr[0]; // this machines ip knock_buffer[1] = hostIP->h_addr[1]; knock_buffer[2] = hostIP->h_addr[2]; knock_buffer[3] = hostIP->h_addr[3]; char* temp = (char*)(&port); // add the port we want to connect to knock_buffer[4] = temp[0]; knock_buffer[5] = temp[1]; int timestamp = time(NULL) + 60; // give us a minute to open the port temp = (char*)(&temp); knock_buffer[6] = temp[0]; knock_buffer[7] = temp[1]; knock_buffer[8] = temp[2]; knock_buffer[9] = temp[3]; int length = strlen(argv[3]); // add the username for (i = 10; i < length + 10; i++) { knock_buffer[i] = argv[3][i]; } knock_buffer[length + 10] = '\0'; /* open server's public key file and obtain key */ int handle = open("server.key", O_RDONLY); if (handle == -1) { printf("Cannot find server key."); return 0; } read(handle, key, KEY_LEN); close(handle); /* take user supplied info and encrypt it */ unsigned char crypted_knock[BUF_LEN]; crypt(knock_buffer, BUF_LEN, key, KEY_LEN, crypted_knock); /* divide info into chunks */ /* send packets within range of ports */ /* unsigned short x, y; int j; for (i = 0, j = 0; i < N_PACKETS; i++) { y = x = 0; if (i % 2) { x = (unsigned short)crypted_knock[j]; y = (( (unsigned short)(crypted_knock[++j]) ) & 0x0F) << 8; y += x; printf("y= %i\n", y); j++; } else { y = ( (unsigned short)(crypted_knock[j]) ) << 4; x = (( (unsigned short)(crypted_knock[++j]) ) & 0xF0) >> 4; y += x; printf("y= %i\n", y); } port = y + i*(N_PORTS/N_PACKETS); send_packet(port); } */ for (i=0; i= key_len) j = 0; ret[i] = buffer[i] ^ key[j]; } } void send_packet(unsigned short port) { char buffer[BUF_LEN]; server.sin_port = htons(port); int i; for (i = 0; i < BUF_LEN; i++) { buffer[i] = (char)(rand() % 256); } // send packet n=sendto(sock, buffer, BUF_LEN, 0, &server, length); if (n < 0) error("Sendto"); } void error(char *msg) { perror(msg); exit(0); }