[tproxy] example of using udp on tproxy4

elyasaf elyasaf at icomsw.com
Sun Nov 30 13:43:02 CET 2008


> While I can see example of using udp on tproxy2 onto the
> redirect-udp-recv.c
> file, I can't find equivalent on tproxy4.
>
> Here are my iptables\ip route redirection lines:
> ${iptables} -t mangle -N DIVERT
> ${iptables} -t mangle -A PREROUTING -p udp -m socket -j DIVERT
> ${iptables} -t mangle -A DIVERT -j MARK --set-mark 1
> ${iptables} -t mangle -A DIVERT -j ACCEPT
> ${iptables} -t mangle -A PREROUTING -p udp --dport 1500 -j TPROXY
> --tproxy-mark 1 --on-port 3127
>
> ip rule add fwmark 1 lookup 100
> ip route add local 0.0.0.0/0 dev lo table 100

#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include <time.h>

#define LOCAL_PROXY_PORT 3127
#define MAX_MSG 100
#ifndef IP_TRANSPARENT
#define IP_TRANSPARENT 19
#endif
#ifndef IP_ORIGADDRS
#define IP_ORIGADDRS      20
#endif
#ifndef IP_RECVORIGADDRS
#define IP_RECVORIGADDRS  IP_ORIGADDRS
#endif
#define CTL_BUF_SIZE 64

int main(int argc, char *argv[]) {
  
  int fd, rc, n, cliLen, flags;
  struct sockaddr_in sourceAddr, destinationAddr , proxyAddr;
  char buf[MAX_MSG];
  struct in_origaddrs *ioa;

  /* socket creation */
  fd=socket(AF_INET, SOCK_DGRAM, 0);
  if(fd<0) {
    printf("%s: cannot open socket \n",argv[0]);
    exit(1);
  }
  flags=1;
  if (setsockopt(fd, SOL_IP,  IP_TRANSPARENT, &flags, sizeof(int)) == -1){
	perror("proxy-setsockopt()  IP_TRANSPARENT error!");
	exit(1);
  }else
	printf("proxy-setsockopt IP_TRANSPARENT is OK...\n");

  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
  setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flags, sizeof(flags));     
  if ( setsockopt(fd, SOL_IP, IP_ORIGADDRS , &flags, sizeof(flags))){
	  perror("proxy-setsockopt()  IP_ORIGADDRS error");
  }else{
	  printf("proxy-setsockopt IP_ORIGADDRS is OK...\n");
  }
  /* bind local server port */
  proxyAddr.sin_family = AF_INET;
  proxyAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  proxyAddr.sin_port = htons(LOCAL_PROXY_PORT);
  rc = bind (fd, (struct sockaddr *) &proxyAddr,sizeof(proxyAddr));
  if(rc<0) {
    printf("%s: cannot bind port number %d \n",argv[0], LOCAL_PROXY_PORT);
    exit(1);
  }

  printf("%s: waiting for data on port UDP %u\n",argv[0],LOCAL_PROXY_PORT);

  /* proxy infinite loop */
  while(1) {
	struct msghdr msg;
    struct cmsghdr *cmsg;
	struct iovec iov;
	char ctl_buf[CTL_BUF_SIZE];
    /* init buffer */
    memset(buf,0,MAX_MSG);
	memset(&msg, 0, sizeof(msg));
	msg.msg_name = &sourceAddr;
	msg.msg_namelen = sizeof(sourceAddr);
	msg.msg_controllen = CTL_BUF_SIZE;
	msg.msg_control = ctl_buf;
	msg.msg_iovlen = 1;
	msg.msg_iov = &iov;
	iov.iov_base = buf;
	iov.iov_len = MAX_MSG;
	
	n = recvmsg(fd, &msg, 0);

    if(n<0) {		
      printf("%s: cannot receive data \n",argv[0]);
	  perror("recvmsg");
      continue;
	}
	printf("%s: source %s:UDP%u : %s \n", 
	   argv[0],inet_ntoa(sourceAddr.sin_addr),
	   ntohs(sourceAddr.sin_port),buf);
	memset(&destinationAddr,0,sizeof(struct sockaddr_in));
	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg =
CMSG_NXTHDR(&msg,cmsg)){
	  if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type ==
IP_RECVORIGADDRS){
		  memcpy(&destinationAddr,(struct sockaddr_in
*)CMSG_DATA(cmsg),sizeof(struct sockaddr_in));
		  destinationAddr.sin_family = AF_INET;
		  printf("%s: destination %s:UDP%u\n", 
			   argv[0],inet_ntoa(destinationAddr.sin_addr),
			   ntohs(destinationAddr.sin_port));

		  send_to_transparenty(buf,n,&sourceAddr,&destinationAddr);
		  //sendto(fd,buf,n,&sourceAddr,&destinationAddr);
	  }
	}
  }/* end of proxy infinite loop */

 return 0;

}
int send_to_transparenty(char *buf,int len,struct sockaddr_in *source,struct
sockaddr_in *destination){
	int fd,flags,i;
	fd=socket(AF_INET, SOCK_DGRAM, 0);
	flags=1;
	if (setsockopt(fd, SOL_IP,  IP_TRANSPARENT, &flags, sizeof(int)) ==
-1){
		perror("destination-setsockopt()  IP_TRANSPARENT error!");
		return;
	}else{
		//printf("destination-setsockopt IP_TRANSPARENT is
OK...\n");
	}
	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
	setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flags, sizeof(flags)); 
	if(bind (fd, (struct sockaddr *) source,sizeof(*source))==-1){
		perror("source-bind() error!");
		return;
	}
	flags=0;
	if(sendto(fd,buf,len,flags,(struct sockaddr
*)destination,sizeof(*destination))==-1){
		perror("destination-sendto() error!");
		return 0;
	}else{
		printf("send to other side\n");
	}
	close(fd);
	return 1;
}



More information about the tproxy mailing list