TCP透明代理

基于Mininet的网络拓扑图:3h.py

#!/usr/bin/python

from mininet.topo import Topo

from mininet.net import Mininet

from mininet.cli import CLI

from mininet.link import TCLink

import time

import datetime

import subprocess

import os,signal

import sys

# 

#    h1------h2------h3             

#

bottleneckbw=6

nonbottlebw=500;  

max_queue_size =bottleneckbw*1000*30/(1500*8) 

net = Mininet( cleanup=True )

h1 = net.addHost('h1',ip='10.0.1.1')

h2 = net.addHost('h2',ip='10.0.1.2')

h3 = net.addHost('h3',ip='10.0.2.2')

c0 = net.addController('c0')

net.addLink(h1,h2,intfName1='h1-eth0',intfName2='h2-eth0',cls=TCLink , bw=nonbottlebw, delay='50ms', max_queue_size=max_queue_size)

net.addLink(h2,h3,intfName1='h2-eth1',intfName2='h3-eth0',cls=TCLink , bw=nonbottlebw, delay='50ms', max_queue_size=max_queue_size)

net.build()

h1.cmd("ifconfig h1-eth0 10.0.1.1/24")

h1.cmd("route add default gw 10.0.1.2 dev h1-eth0")

h1.cmd('sysctl net.ipv4.ip_forward=1')



h2.cmd("ifconfig h2-eth0 10.0.1.2/24")

h2.cmd("ifconfig h2-eth1 10.0.2.1/24")

h2.cmd("ip route add to 10.0.2.0/24 via 10.0.2.2")

h2.cmd("ip route add to 10.0.1.0/24 via 10.0.1.1")

#tproxy
h2.cmd(" iptables -t nat -N MY_TCP")

h2.cmd("iptables -t nat -A PREROUTING -j MY_TCP")

h2.cmd("iptables -t nat -A MY_TCP -p tcp -d 10.0.2.2 -j REDIRECT --to-ports 2223")

h2.cmd("iptables -N MY_TCP")

h2.cmd("iptables -A INPUT -j MY_TCP")

h2.cmd(" iptables -A MY_TCP -p tcp --dport 2223 -j ACCEPT")

h2.cmd('sysctl net.ipv4.ip_forward=1')
h3.cmd("ifconfig h3-eth0 10.0.2.2/24")
h3.cmd("route add default gw 10.0.2.1 dev h3-eth0")
h3.cmd('sysctl net.ipv4.ip_forward=1')


h3.cmd('sysctl net.ipv4.ip_forward=1')



net.start()

time.sleep(1)

CLI(net)

net.stop()

客户端程序:socket_client_tcp.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
#define PORT 23			//目标地址端口号
#define ADDR "10.0.2.2" //目标地址IP
int main()
{
     
	int yes=1;
	int iSocketFD = 0; //socket句柄
	unsigned int iRemoteAddr = 0;
	struct sockaddr_in stRemoteAddr = {
     0}; //对端,即目标地址信息,服务器端地址
	socklen_t socklen = 0;  	
	char buf[4096] = {
     0}; //存储接收到的数据
 
	iSocketFD = socket(AF_INET, SOCK_STREAM, 0); // 建立客户端socket
	if(0 > iSocketFD)
	{
     
		printf("创建socket失败!\n");
		return 0;
	}	
 
	//定义要连接的代理服务器端地址
	stRemoteAddr.sin_family = AF_INET;
	stRemoteAddr.sin_port = htons(PORT);
	inet_pton(AF_INET, ADDR, &iRemoteAddr);
	stRemoteAddr.sin_addr.s_addr=iRemoteAddr;
	
	//连接到代理服务器:连接方法: 传入句柄,目标地址,和大小
	if(0 > connect(iSocketFD, (struct sockaddr *)&stRemoteAddr, sizeof(stRemoteAddr)))
	{
     
		printf("连接失败!\n");
		//printf("connect failed:%d",errno);//失败时也可打印errno
	}else{
     
		printf("连接成功!\n");
		//向代理服务器发送数据
		send(iSocketFD, "客户端-客户端-客户端", strlen("客户端-客户端-客户端"), 0);
		//从代理服务器接收数据
		recv(iSocketFD, buf, sizeof(buf), 0);// 将接收数据打入buf,参数分别是句柄,储存处,最大长度,其他信息(设为0即可)。 
		printf("Received:%s\n", buf);
	}
	
	close(iSocketFD);//关闭socket	
	return 0;
}

代理服务器程序:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include           /* See NOTES */
#include 
#include 
#include 
#define PORT 2223		//端口号
#define BACKLOG 5	//最大监听数
 
int main()
{
     
	int yes=1;
	int iSocketFD = 0;  //socket句柄
	int iRecvLen = 0;   //接收成功后的返回值
	int new_fd = 0; 	//建立连接后的句柄
	char buf[4096] = {
     0}; //
	socklen_t n = 0;
	int ret = 0;
	struct sockaddr_in stLocalAddr = {
     0}; //本地地址信息结构图,下面有具体的属性赋值
	struct sockaddr_in stRemoteAddr = {
     0}; //对方地址信息
	socklen_t socklen = 0;  
 
	iSocketFD = socket(AF_INET, SOCK_STREAM, 0); //建立socket
	if(0 > iSocketFD)
	{
     
		printf("创建socket失败!\n");
		return 0;
	}	
 
	stLocalAddr.sin_family = AF_INET;  /*该属性表示接收本机或其他机器传输*/
	stLocalAddr.sin_port = htons(PORT); /*端口号*/
	stLocalAddr.sin_addr.s_addr=htonl(INADDR_ANY); /*IP,括号内容表示本机IP*/

	if(setsockopt(iSocketFD, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) 
            == -1){
     
        perror("setsockopt (SO_REUSEADDR): ");
        close(iSocketFD);
        return 0;
    }
 	//本地socket捕获数据包,为socket设置IP_TRANSPARENT选项
	  if(setsockopt(iSocketFD, SOL_IP, IP_TRANSPARENT, &yes, sizeof(yes)) 
            == -1){
     
        perror("setsockopt (IP_TRANSPARENT): ");
        close(iSocketFD);
        return 0;
    }

	//绑定地址结构体和socket
	if(0 > bind(iSocketFD, (struct sockaddr *)&stLocalAddr, sizeof(stLocalAddr)))
	{
     
		printf("绑定失败!\n");
		return 0;
	}
 
	//开启监听 ,第二个参数是最大监听数
	if(0 > listen(iSocketFD, BACKLOG))
	{
     
		printf("监听失败!\n");
		return 0;
	}
 	printf("阻塞在这里0\n");
	printf("iSocketFD: %d\n", iSocketFD);	
	//在这里阻塞知道接收到消息,参数分别是socket句柄,接收到的地址信息以及大小
	while(1)
	{
     
		printf("##############");	
		new_fd = accept(iSocketFD, (struct sockaddr *)&stRemoteAddr, &socklen);
		printf("new_fd: %d\n", new_fd);	
		if(0 > new_fd)
		{
     
			printf("接收失败!\n");
			return 0;
		}else{
     
			printf("接收成功!\n");
			n = sizeof(struct sockaddr_in);
			ret = getsockopt(new_fd, SOL_IP, SO_ORIGINAL_DST, &stRemoteAddr, &n);
			if(0 != ret)
			{
     
				printf ("error getting original destination address.\n");
				close (new_fd);
				return -1;
			}
			stRemoteAddr.sin_family = AF_INET; 
			printf("original destination address %u:%hu\n", ntohl(stRemoteAddr.sin_addr.s_addr), ntohs(stRemoteAddr.sin_port));	
			//发送内容,参数分别是连接句柄,内容,大小,其他信息(设为0即可) 
			recv(new_fd, buf, sizeof(buf), 0);
			printf("从客户端上接收到的信息是:%s\n", buf);
			//send(new_fd, "这是代理服务器接收成功后发回的信息!", sizeof("这是代理服务器接收成功后发回的信息!"), 0);
 
			/* 连接服务器*/
			int iSockClientFD = 0;
			iSockClientFD = socket(AF_INET, SOCK_STREAM, 0);
			if(0 > iSockClientFD)					
			{
     
				printf("代理向服务器建立连接失败!\n");
				return 0;
			}
			if(0 > connect(iSockClientFD, (struct sockaddr *)&stRemoteAddr, sizeof(stRemoteAddr)))
			{
     
				printf("代理向服务器建立连接失败!\n");
				return 0;
			}
			send(iSockClientFD, buf, sizeof(buf), 0);//向服务器发送消息
			recv(iSockClientFD, buf, sizeof(buf), 0);//接收来自服务器的消息
			printf("从服务器端收到的消息:%s\n", buf);//打印接收到的来自服务器的消息
			send(new_fd, buf, sizeof(buf), 0);//向客户端发送消息		
			sleep(5);	
		}
	}
	close(new_fd);
	close(iSocketFD);
 
	return 0;
}

TCP服务器程序

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 23		//端口号
#define BACKLOG 5	//最大监听数
 
int main()
{
     
	int iSocketFD = 0;  //socket句柄
	int iRecvLen = 0;   //接收成功后的返回值
	int new_fd = 0; 	//建立连接后的句柄
	char buf[4096] = {
     0}; 
	struct sockaddr_in stLocalAddr = {
     0}; //本地地址信息结构图,下面有具体的属性赋值
	struct sockaddr_in stRemoteAddr = {
     0}; //对方地址信息
	socklen_t socklen = 0;  	
 
	iSocketFD = socket(AF_INET, SOCK_STREAM, 0); //建立socket
	if(0 > iSocketFD)
	{
     
		printf("创建socket失败!\n");
		return 0;
	}	
 
	stLocalAddr.sin_family = AF_INET;  /*该属性表示接收本机或其他机器传输*/
	stLocalAddr.sin_port = htons(PORT); /*绑定端口号*/
	stLocalAddr.sin_addr.s_addr=htonl(INADDR_ANY); /*IP,INADDR_IP表示任何IP地址*/
 
	//绑定地址结构体和socket
	if(0 > bind(iSocketFD, (struct sockaddr *)&stLocalAddr, sizeof(stLocalAddr)))
	{
     
		printf("绑定失败!\n");
		return 0;
	}
 
	//开启监听 ,第二个参数是最大监听数
	if(0 > listen(iSocketFD, BACKLOG))
	{
     
		printf("监听失败!\n");
		return 0;
	}
 
	printf("iSocketFD: %d\n", iSocketFD);	
	//在这里阻塞知道接收到消息,参数分别是socket句柄,接收到的地址信息以及大小 
	//会阻塞进程,直到有客户端连接上来为止
	while(1){
     
		new_fd = accept(iSocketFD, (struct sockaddr *)&stRemoteAddr, &socklen);
		if(0 > new_fd)
		{
     
			printf("接收失败!\n");
			return 0;
		}else{
     
			printf("接收成功!\n");
			//发送内容,参数分别是连接句柄,内容,大小,其他信息(设为0即可) 
			//send(new_fd, "这是服务器接收成功后发回的信息!", sizeof("这是服务器接收成功后发回的信息!"), 0);
		}
 
		printf("new_fd: %d\n", new_fd);	
		iRecvLen = recv(new_fd, buf, sizeof(buf), 0);	
		if(0 >= iRecvLen)    //对端关闭连接 返回0
		{
     	
			printf("接收失败或者对端关闭连接!\n");
		}else{
     
			//接收并打印代理服务器传过来的数据
			printf("从客户端接收到的消息: %s\n", buf);
		}
 
		//向代理服务器发送数据
		send(new_fd, "服务器-服务器-服务器" , strlen("服务器-服务器-服务器"), 0);
	}
	sleep(5);
 
	close(new_fd);
	close(iSocketFD);
 
	return 0;
}

相关资料:
基于本篇博客来实现
添加链接描述
添加链接描述

你可能感兴趣的:(C++)