190 likes | 274 Views
Introduction to Information Security. Networking. Transmission Control Protocol (aka TCP). Most widely used protocol A TCP Connection is based on 6 crucial parmeters : Source IP Destination IP Source port Destination port Source byte counter Destination byte counter. TCP/IP Continued.
E N D
Introduction to Information Security Networking
Transmission Control Protocol (aka TCP) • Most widely used protocol • A TCP Connection is based on 6 crucial parmeters: • Source IP • Destination IP • Source port • Destination port • Source byte counter • Destination byte counter
TCP/IP Continued • In order to establish a tcp connection a 3-way handshake occurs. • Once the handshake is establish and the connection is up and running tcp ensures: • Delivery of _all_ packets • Delivery of in order • Delivery with no errors.
Server implementation • The server listens on a specific port (aka the destination port) • Once a connection is established, the server can accept more connections while handling the first connection. • Establish multi processing of connections can be gained by: • Fork() – Multi process solution. • Multi-Threaded solutions. • Select() – Single process solutions • Other OS specific solutions.
Client implementation • Usually handles only one connection at a time. (extreme contrary example: uTorrent). • Source port is randomized by operating system.
Network Programming • Most popular guide ever released for network programming is beej’s guide which is a very good starter reference • http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
Server implementation in C (taken from beej) - includes /* ** server.c - a stream socket server demo */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <signal.h>
C-Server Cleanup and defines #define MYPORT 3490 // the port users will be connecting to #define BACKLOG 10 // how many pending connections queue will hold //Cleaning up dead child processes: void sigchld_handler(int s) { while(waitpid(-1, NULL, WNOHANG) > 0); }
C-Server main int main(void) { intsockfd, new_fd; // listen on sock_fd, new connection on new_fd structsockaddr_inmy_addr; // my address information structsockaddr_intheir_addr; // connector’s address information socklen_tsin_size; structsigactionsa; int yes=1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(MYPORT); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
C-Server continued if (bind(sockfd, (structsockaddr *)&my_addr, sizeof(structsockaddr)) == -1) { perror("bind"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror("listen"); exit(1); } sa.sa_handler = sigchld_handler; // reap all dead processes sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); }
C-Server continued while(1) { // main accept() loop sin_size = sizeof(structsockaddr_in); if ((new_fd = accept(sockfd, (structsockaddr *)&their_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr)); if (!fork()) { // this is the child process close(sockfd); // child doesn't need the listener if (send(new_fd, "Hello, world!\n", 14, 0) == -1) perror("send"); close(new_fd); exit(0); } close(new_fd); // parent doesn't need this } return 0; }
C-Client - includes /* ** client.c - a stream socket client demo */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 3490 // the port client will be connecting to #define MAXDATASIZE 100 // max number of bytes we can get at once
C-Client main • int main(intargc, char *argv[]) • { • intsockfd, numbytes; • char buf[MAXDATASIZE]; • structhostent *he; • structsockaddr_intheir_addr; // connector's address information • if (argc != 2) { • fprintf(stderr,"usage: client hostname\n"); • exit(1); • } • if ((he=gethostbyname(argv[1])) == NULL) { // get the host info • perror("gethostbyname"); • exit(1); • } • if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { • perror("socket"); • exit(1); • }
C-Client main continued • their_addr.sin_family = AF_INET; // host byte order • their_addr.sin_port = htons(PORT); // short, network byte order • their_addr.sin_addr = *((structin_addr *)he->h_addr); • memset(&(their_addr.sin_zero), 8); // zero the rest of the struct • if (connect(sockfd, (structsockaddr *)&their_addr, sizeof(structsockaddr)) == -1) { • perror("connect"); • exit(1); • } • if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) { • perror("recv"); • exit(1); • } • buf[numbytes] = '\0'; • printf("Received: %s",buf); • close(sockfd); • return 0; • }
Python client #!usr/bin/python from socket import * PORT = 3490 def main(): sock = socket(AF_INET, SOCK_STREAM) sock.connect(("127.0.0.1", PORT)) res = sock.recv(1000) # 1000 = Maximum number of bytes to # receive, however, it may return with less bytes # than expected print res sock.close() if __name__ == '__main__': main()
Python server example #!usr/bin/python from socket import * PORT = 3490 def main(): sock = socket(AF_INET, SOCK_STREAM) sock.bind(("0.0.0.0", PORT)) sock.listen(10) # set backlog while 1: (clisock, addr) = sock.accept() print "Got incoming connection..." res = clisock.send("Hello, World!") clisock.close() sock.close() if __name__ == '__main__': main()
File descriptors • Serially assigned to process and can be shared between processes. • Reference based (file closes when the last descriptor closes) • Popular descriptors: • 0 – stdin • 1 – stdout • 2 – stderr • 3 – graphics • Can be dup()licatedusing dup() and dup2()
dup2() • Using dup2() can be used to easily connect processes inputs and outputs to an existing TCP connection! • Assuming sockfdis an already created and connected file descriptor we run: dup2(sockfd, 0); // dup standard input dup2(sockfd,1); // dup standard output dup2(sockfd,2); // dup standard error output • Now we can run: execv(“someprocess”, NULL)