proxy.c revision 31183
131183Speter/* 231183Speter * Sample transparent proxy program. 331183Speter * 431183Speter * Sample implementation of a program which intercepts a TCP connectiona and 531183Speter * just echos all data back to the origin. Written to work via inetd as a 631183Speter * "nonwait" program running as root; ie. 731183Speter * tcpmux stream tcp nowait root /usr/local/bin/proxy proxy 831183Speter * with a NAT rue like this: 931183Speter * rdr smc0 0/0 port 80 -> 127.0.0.1/32 port 1 1031183Speter */ 1131183Speter#include <stdio.h> 1231183Speter#include <string.h> 1331183Speter#include <fcntl.h> 1431183Speter#include <syslog.h> 1531183Speter#if !defined(__SVR4) && !defined(__svr4__) 1631183Speter#include <strings.h> 1731183Speter#else 1831183Speter#include <sys/byteorder.h> 1931183Speter#endif 2031183Speter#include <sys/types.h> 2131183Speter#include <sys/time.h> 2231183Speter#include <sys/param.h> 2331183Speter#include <stdlib.h> 2431183Speter#include <unistd.h> 2531183Speter#include <stddef.h> 2631183Speter#include <sys/socket.h> 2731183Speter#include <sys/ioctl.h> 2831183Speter#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) 2931183Speter# include <sys/ioccom.h> 3031183Speter# include <sys/sysmacros.h> 3131183Speter#endif 3231183Speter#include <netinet/in.h> 3331183Speter#include <netinet/in_systm.h> 3431183Speter#include <netinet/ip.h> 3531183Speter#include <netinet/tcp.h> 3631183Speter#include <net/if.h> 3731183Speter#include <netdb.h> 3831183Speter#include <arpa/nameser.h> 3931183Speter#include <arpa/inet.h> 4031183Speter#include <resolv.h> 4131183Speter#include <ctype.h> 4231183Speter#include "netinet/ip_compat.h" 4331183Speter#include "netinet/ip_fil.h" 4431183Speter#include "netinet/ip_proxy.h" 4531183Speter#include "netinet/ip_nat.h" 4631183Speter 4731183Speter 4831183Spetermain(argc, argv) 4931183Speterint argc; 5031183Speterchar *argv[]; 5131183Speter{ 5231183Speter struct sockaddr_in sin, sloc, sout; 5331183Speter natlookup_t natlook; 5431183Speter char buffer[512]; 5531183Speter int namelen, fd, n; 5631183Speter 5731183Speter /* 5831183Speter * get IP# and port # of the remote end of the connection (at the 5931183Speter * origin). 6031183Speter */ 6131183Speter namelen = sizeof(sin); 6231183Speter if (getpeername(0, (struct sockaddr *)&sin, &namelen) == -1) { 6331183Speter perror("getpeername"); 6431183Speter exit(-1); 6531183Speter } 6631183Speter 6731183Speter /* 6831183Speter * get IP# and port # of the local end of the connection (at the 6931183Speter * man-in-the-middle). 7031183Speter */ 7131183Speter namelen = sizeof(sin); 7231183Speter if (getsockname(0, (struct sockaddr *)&sloc, &namelen) == -1) { 7331183Speter perror("getsockname"); 7431183Speter exit(-1); 7531183Speter } 7631183Speter 7731183Speter /* 7831183Speter * Build up the NAT natlookup structure. 7931183Speter */ 8031183Speter bzero((char *)&natlook, sizeof(natlook)); 8131183Speter natlook.nl_outip = sin.sin_addr; 8231183Speter natlook.nl_inip = sloc.sin_addr; 8331183Speter natlook.nl_flags = IPN_TCP; 8431183Speter natlook.nl_outport = sin.sin_port; 8531183Speter natlook.nl_inport = sloc.sin_port; 8631183Speter 8731183Speter /* 8831183Speter * Open the NAT device and lookup the mapping pair. 8931183Speter */ 9031183Speter fd = open(IPL_NAT, O_RDONLY); 9131183Speter if (ioctl(fd, SIOCGNATL, &natlook) == -1) { 9231183Speter perror("ioctl"); 9331183Speter exit(-1); 9431183Speter } 9531183Speter close(fd); 9631183Speter /* 9731183Speter * Log it 9831183Speter */ 9931183Speter syslog(LOG_DAEMON|LOG_INFO, "connect to %s,%d", 10031183Speter inet_ntoa(natlook.nl_realip), natlook.nl_realport); 10131183Speter printf("connect to %s,%d\n", 10231183Speter inet_ntoa(natlook.nl_realip), ntohs(natlook.nl_realport)); 10331183Speter 10431183Speter /* 10531183Speter * Just echo data read in from stdin to stdout 10631183Speter */ 10731183Speter while ((n = read(0, buffer, sizeof(buffer))) > 0) 10831183Speter if (write(1, buffer, n) != n) 10931183Speter break; 11031183Speter close(0); 11131183Speter} 112