proxy.c revision 31183
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
48main(argc, argv)
49int argc;
50char *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), 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