1 /* 2 * Sample transparent proxy program. 3 * 4 * Sample implementation of a program which intercepts a TCP connectiona and 5 * just echos all data back to the origin. Written to work via inetd as a 6 * "nonwait" program running as root; ie. 7 * tcpmux stream tcp nowait root /usr/local/bin/proxy proxy 8 * with a NAT rue like this: 9 * rdr smc0 0/0 port 80 -> 127.0.0.1/32 port 1 10 */ 11 #include <stdio.h> 12 #include <string.h> 13 #include <fcntl.h> 14 #include <syslog.h> 15 #if !defined(__SVR4) && !defined(__svr4__) 16 #include <strings.h> 17 #else 18 #include <sys/byteorder.h> 19 #endif 20 #include <sys/types.h> 21 #include <sys/time.h> 22 #include <sys/param.h> 23 #include <stdlib.h> 24 #include <unistd.h> 25 #include <stddef.h> 26 #include <sys/socket.h> 27 #include <sys/ioctl.h> 28 #if defined(sun) && (defined(__svr4__) || defined(__SVR4)) 29 # include <sys/ioccom.h> 30 # include <sys/sysmacros.h> 31 #endif 32 #include <netinet/in.h> 33 #include <netinet/in_systm.h> 34 #include <netinet/ip.h> 35 #include <netinet/tcp.h> 36 #include <net/if.h> 37 #include <netdb.h> 38 #include <arpa/nameser.h> 39 #include <arpa/inet.h> 40 #include <resolv.h> 41 #include <ctype.h> 42 #include "netinet/ip_compat.h" 43 #include "netinet/ip_fil.h" 44 #include "netinet/ip_proxy.h" 45 #include "netinet/ip_nat.h" 46 47 48 main(argc, argv) 49 int argc; 50 char *argv[]; 51 { 52 struct sockaddr_in sin, sloc, sout; 53 natlookup_t natlook; 54 char buffer[512]; 55 int namelen, fd, n; 56 57 /* 58 * get IP# and port # of the remote end of the connection (at the 59 * origin). 60 */ 61 namelen = sizeof(sin); 62 if (getpeername(0, (struct sockaddr *)&sin, &namelen) == -1) { 63 perror("getpeername"); 64 exit(-1); 65 } 66 67 /* 68 * get IP# and port # of the local end of the connection (at the 69 * man-in-the-middle). 70 */ 71 namelen = sizeof(sin); 72 if (getsockname(0, (struct sockaddr *)&sloc, &namelen) == -1) { 73 perror("getsockname"); 74 exit(-1); 75 } 76 77 /* 78 * Build up the NAT natlookup structure. 79 */ 80 bzero((char *)&natlook, sizeof(natlook)); 81 natlook.nl_outip = sin.sin_addr; 82 natlook.nl_inip = sloc.sin_addr; 83 natlook.nl_flags = IPN_TCP; 84 natlook.nl_outport = sin.sin_port; 85 natlook.nl_inport = sloc.sin_port; 86 87 /* 88 * Open the NAT device and lookup the mapping pair. 89 */ 90 fd = open(IPL_NAT, O_RDONLY); 91 if (ioctl(fd, SIOCGNATL, &natlook) == -1) { 92 perror("ioctl"); 93 exit(-1); 94 } 95 close(fd); 96 /* 97 * Log it 98 */ 99 syslog(LOG_DAEMON|LOG_INFO, "connect to %s,%d", 100 inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport)); 101 printf("connect to %s,%d\n", 102 inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport)); 103 104 /* 105 * Just echo data read in from stdin to stdout 106 */ 107 while ((n = read(0, buffer, sizeof(buffer))) > 0) 108 if (write(1, buffer, n) != n) 109 break; 110 close(0); 111 } 112