ICMP traffic capture and forwarding proxy (2)

Source: Internet
Author: User
The ICMP packet sent from client C to server s is intercepted when it passes through the local p. The previous article describes how to obtain the original destination address. You must forward the data to the original destination address S, and forward the response from the original destination address to the client. To implement transparent proxy, the source address of the ICMP response you return to the client must be the original destination address s of the client request. Because raw socket is used, you cannot use the socket option of ip_transparent to bind a non-local address (BIND reports an error: the address cannot be bound). Therefore, use the socket option of ip_hdrincl, manually fill in the IP header to set the source address to S and the destination address to C (in fact, it is to reverse the two addresses of the ICMP packet received from the client ).
Socklen_t sender_len;
Struct msghdr MSG;
Struct iovec IOV;
Struct sockaddr_in sender_addr;
Sender_len = sizeof (sender_addr );
Char Buf [2048] = {0 };
Int Len = 0;
Char cmsg_buf [1, 2048] = {0 };

MSG. msg_name = & sender_addr;
MSG. msg_namelen = sender_len;
MSG. msg_iov = & IOV;
MSG. msg_iovlen = 1;
MSG. msg_iov-> iov_base = Buf;
MSG. msg_iov-> iov_len = 2048;
MSG. msg_control = cmsg_buf;
MSG. msg_controllen = 2048;
MSG. msg_flags = 0;

// Receive ICMP packets from the client
Len = recvmsg (sockfd, & MSG, 0 );
If (LEN =-1 ){
Perror ("recvmsg ()");
} Else if (LEN = 0 ){
Printf ("Connection closed \ n ");
} Else {
Printf ("read from client: Len [% d] \ n -- content:", Len );
Print_data (BUF, Len );

Struct cmsghdr * cmsg = NULL;
For (cmsg = cmsg_firsthdr (& MSG );
Cmsg! = NULL;
Cmsg = cmsg_nxthdr (& MSG, cmsg ))
{
// Ignore the Control headers that don't match what we want
If (cmsg-> cmsg_level! = Ipproto_ip |
Cmsg-> cmsg_type! = Ip_pktinfo)
{
Continue;
}
Struct in_pktinfo * Pi = cmsg_data (cmsg );
// Printf ("ipi_spec_dst: % s \ n", inet_ntoa (Pi-> ipi_spec_dst ));
// Printf ("ipi_addr: % s \ n", inet_ntoa (Pi-> ipi_addr ));
Char sender_ip [32] = {0 };
Int sender_port = 0;
Transfer_sock_addr (& sender_addr, sender_ip, 32, & sender_port );
Printf ("Source IP: % s port: % d \ n", sender_ip, sender_port );
// At This Point, peeraddr is the source sockaddr
// Pi-> ipi_spec_dst is the destination in_addr
// Pi-> ipi_addr is the processing ing interface in_addr
}
Char orig_ip [32] = {0 };
Int orig_port = 0;
Struct sockaddr_in * orig_addr;
For (cmsg = cmsg_firsthdr (& MSG); cmsg! = NULL;
Cmsg = cmsg_nxthdr (& MSG, cmsg )){
If (cmsg-> cmsg_level = sol_ip
& Cmsg-> cmsg_type = ip_origdstaddr ){
Orig_addr = (struct sockaddr_in *) cmsg_data (cmsg );
Transfer_sock_addr (orig_addr, orig_ip, 32, & orig_port );
Break;
}
}
If (cmsg = NULL ){
Printf ("ip_origdstaddr not enabled or small buffer or I/O error ");
Return;
}
Printf ("original destination IP: % s-Port: % d \ n", orig_ip, orig_port );


// Struct sockaddr_in sin;
// Memset (& sin, 0, sizeof (SIN ));
// Sin. sin_family = af_inet;
// Sin. sin_addr.s_addr = inet_addr ("192.168.128.2 ");
// Sin. sin_port = htons (orig_port );


Int I;
Int iphdrlen; // IP header length
Struct IP * IP;
Struct ICMP * ICMP;

IP = (struct IP *) BUF;
Iphdrlen = IP-> ip_hl <2; // calculate the length of the IP header, that is, the length of the IP header multiplied by 4
ICMP = (struct ICMP *) (BUF + iphdrlen); // redirects to the ICMP header over the IP Address Header
Len-= iphdrlen;
// Forward to the server
Printf ("sendto Server \ n ");
Sendto (sockfd, ICMP, Len, 0, (struct sockaddr *) & orig_addr, sizeof (struct sockaddr ));
// Receive ICMP response from the server
Printf ("recvfrom Server \ n ");
If (LEN = recvfrom (sockfd, Buf, 2048,0,
(Struct sockaddr *) & from, & fromlen) <0 ){
Perror ("recvfrom error ");
Return-1;
}


Int sock_fd;
Int flag = 1;

If (sock_fd = socket (af_inet, sock_raw, ipproto_icmp) <0 ){
Perror ("socket ()");
Return-1;
}
If (setsockopt (sock_fd, ipproto_ip, ip_hdrincl, & flag, sizeof (INT) <0 ){
Perror ("setsockopt ()-ip_hdrincl ");
Return-1;
}
If (connect (sock_fd, & sin, sizeof (struct sockaddr_in) <0 ){
Close (sockfd );
Perror ("Connect error ");
Return-1;
}
IP = (struct IP *) BUF;
Struct in_addr ip_src, ip_dst;
Ip_src.s_addr = inet_addr (orig_ip );
Ip_dst.s_addr = sender_addr.sin_addr.s_addr;
IP-> ip_src = ip_src;
IP-> ip_dst = ip_dst;
Iphdrlen = IP-> ip_hl <2; // calculate the length of the IP header, that is, the length of the IP header multiplied by 4
// ICMP = (struct ICMP *) (BUF + iphdrlen); // redirects to the ICMP header over the IP Address Header
// Len-= iphdrlen;
// Send the response to the client
Printf ("sendto client \ n ");
Sendto (sock_fd, Buf, Len, 0, (struct sockaddr *) & sender_addr, sizeof (struct sockaddr ));
Close (sock_fd );

ICMP traffic capture and forwarding proxy (2)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.