How to use iptables to connect proxy server

1,506

Solution 1

Try this rule:

iptables -t nat -A PREROUTING -i eth0 -s ! 192.168.0.2 -p tcp --dport 80 -j DNAT --to 192.168.0.2:3128
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -d 192.168.0.2 -j SNAT --to 192.168.0.1
iptables -A FORWARD -s 192.168.0.0/24 -d 192.168.0.2 -i eth0 -o eth0 -p tcp --dport 3128 -j ACCEPT

where:

192.168.0.2 - proxy server IP (Squid, etc);
192.168.0.1 - router IP (where started iptables);
192.168.0.0/24 - your local network

I could be wrong, check carefully.

Solution 2

Without having tested it I think the solution @ymn is valid for HTTP, but I don't think you can get around specifying an equivalent line for HTTPS - indeed any such solution should throw up certificate errors etc because you are, in-effect, doing a man-in-the-middle attack on your own network.

(You may be able to get round this - to some degree - but its not a good idea as you are stripping the security SSL gives. Have a look at sslstrip - http://www.thoughtcrime.org/software/sslstrip/)

Maybe a better middle ground might be to try doing proxy autoconfiguration (WPAD with DHCP) - http://wiki.squid-cache.org/SquidFaq/ConfiguringBrowsers#Fully_Automatically_Configuring_Browsers_for_WPAD

Share:
1,506

Related videos on Youtube

es483
Author by

es483

Updated on September 18, 2022

Comments

  • es483
    es483 over 1 year

    While writing a program using RAW and SOCK_DRAM UDP sockets, I noticed that the Ethernet Maximum Transmission Unit is always representing a limit to the data I can send without incurring into fragmentation, even if the socket is strictly bound to a wireless interface (using bind()) and the packets are always transmitted on the air using Wi-Fi (802.11), without any wired network segment in between.

    I knew the 802.11 MTU to be 2346 B (is it correct?), which is larger than 1500 B. But if I try to transmit more than the Ethernet MTU size (1500 B), I get fragmentation when using UDP sockets and a "message too big" error (errno 90, EMSGSIZE) when using sendto() on RAW sockets.

    Is this due to the fact that, from the point of view of the user applications, 802.11 packets are seen as 802.3 packets which are then converted and managed inside the kernel and hardware devices? Why is this limit applying even if I could transmit larger frames with "Wi-Fi"?

    Edit: sample code to reproduce the problem for RAW sockets

    Here is a sample code, extracted from the original one, that you can compile with gccand use to reproduce the problem I described before.

    When using RAW sockets a message over 1500 B is explicitely rejected, setting errno, even when the socket is bound to a wireless interface.

    Here is the code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <linux/wireless.h>
    #include <sys/socket.h>
    #include <linux/if_packet.h>
    #include <net/ethernet.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <sys/ioctl.h>
    
    #define DEVNAME "wlp2s0"
    #define DESTINATIONMAC_INITIALIZER {0x9C,0xD2,0x1E,0x20,0x91,0xE5}
    
    #define SIZEOK 1500
    #define SIZEWRONG 1501
    
    int main (int argc, char **argv) {
        // wlanLookup() variables, for interface name, source MAC address and return value
        char devname[]=DEVNAME;
        int ifindex;
    
        int descriptor; // Socket descriptor
        struct sockaddr_ll addrll; // sockaddr_ll address structure
    
        struct ifreq wifireq;
    
        struct ether_header etherHeader;
    
        unsigned char bufferok[SIZEOK];
        unsigned char bufferwrong[SIZEWRONG];
    
        unsigned char *packetok=NULL;
        unsigned char *packetwrong=NULL;
    
        // Source and destination MAC addresses
        unsigned char macsrc[6];
        unsigned char macdst[6]=DESTINATIONMAC_INITIALIZER;
    
        // Size variables
        int sentbytes;
        size_t sizeok_final=sizeof(struct ether_header)+SIZEOK; // Size of the ok buffer + size of struct ether_header
        size_t sizewrong_final=sizeof(struct ether_header)+SIZEWRONG; // Size of the ok buffer + size of struct ether_header
    
        if(SIZEWRONG<SIZEOK) {
            fprintf(stderr,"Error: in this sample code, SIZEWRONG (%d) must be >= than SIZEOK (%d)\n",SIZEWRONG,SIZEOK);
            exit(EXIT_FAILURE);
        }
    
        descriptor=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
    
        if(descriptor==-1) {
            perror("socket() error");
            exit(EXIT_FAILURE);
        }
    
        // Get interface index of the interface
        strncpy(wifireq.ifr_name,devname,IFNAMSIZ);
        if(ioctl(descriptor,SIOCGIFINDEX,&wifireq)!=-1) {
            ifindex=wifireq.ifr_ifindex;
        } else {
            perror("ioctl() error");
            close(descriptor);
            exit(EXIT_FAILURE);
        }
    
        fprintf(stdout,"Using interface: %s (index: %x)\n",DEVNAME,ifindex);
    
        // Prepare sockaddr_ll structure
        memset(&addrll,0,sizeof(addrll));
        addrll.sll_ifindex=ifindex;
        addrll.sll_family=AF_PACKET;
        addrll.sll_protocol=htons(ETH_P_ALL);
    
        // Bind to the wireless interface
        if(bind(descriptor,(struct sockaddr *) &addrll,sizeof(addrll))<0) {
            perror("Cannot bind to interface: bind() error");
            close(descriptor);
            exit(EXIT_FAILURE);
        }
    
        fprintf(stdout,"Bound to interface: %s (index: %x)\n",DEVNAME,ifindex);
    
        // Populate both buffers with some data
        for(int i=0;i<SIZEWRONG;i++) {
            if(i<SIZEOK) {
                bufferok[i]=(unsigned char) (i & 15); // Fill each byte with a cyclic sequence 0x00, 0x01, 0x02, ... 0x0F, 0x00, 0x01, ...
            }
            bufferwrong[i]=(unsigned char) (i & 15);
        }
    
        // Get source MAC address
        strncpy(wifireq.ifr_name,devname,IFNAMSIZ); 
        if(ioctl(descriptor,SIOCGIFHWADDR,&wifireq)!=-1) {
            memcpy(macsrc,wifireq.ifr_hwaddr.sa_data,6);
        } else {
            perror("Cannot get source MAC address: ioctl() error");
            close(descriptor);
        }
        fprintf(stdout,"Source MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",macsrc[0],macsrc[1],macsrc[2],macsrc[3],macsrc[4],macsrc[5]);
        fprintf(stdout,"Destination MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",macdst[0],macdst[1],macdst[2],macdst[3],macdst[4],macdst[5]);
    
        // Fill struct ether_header
        memcpy(etherHeader.ether_dhost,macdst,ETHER_ADDR_LEN);
        memcpy(etherHeader.ether_shost,macsrc,ETHER_ADDR_LEN);
        // Using local experimental ethertype for the sake of this sample code, but the effect is the same for any other EtherType
        etherHeader.ether_type=htons(0x88B5);
    
        packetok=malloc(sizeok_final*sizeof(unsigned char));
        if(!packetok) {
            perror("malloc() error");
            close(descriptor);
            exit(EXIT_FAILURE);
        }
        packetwrong=malloc(sizewrong_final*sizeof(unsigned char));
    
        if(!packetwrong) {
            perror("malloc() error");
            free(packetok);
            close(descriptor);
            exit(EXIT_FAILURE);
        }
    
        // Generate the complete packet buffers
        // Packet OK
        memcpy(packetok,&etherHeader,sizeof(struct ether_header));
        memcpy(packetok+sizeof(struct ether_header),bufferok,sizeok_final);
    
        // Packet WRONG
        memcpy(packetwrong,&etherHeader,sizeof(struct ether_header));
        memcpy(packetwrong+sizeof(struct ether_header),bufferwrong,sizewrong_final);
    
        sentbytes=sendto(descriptor,packetok,sizeok_final,0,(struct sockaddr *)&addrll,sizeof(struct sockaddr_ll));
    
        perror("Packet OK errors (if any)");
        fprintf(stdout,"Packet OK: sent %d bytes.\n",sentbytes);
    
        sentbytes=sendto(descriptor,packetwrong,sizewrong_final,0,(struct sockaddr *)&addrll,sizeof(struct sockaddr_ll));
    
        perror("Packet WRONG errors (if any)");
        fprintf(stdout,"Packet WRONG: sent %d bytes.\n",sentbytes);
    
        close(descriptor);
    
        return 0;
    }
    

    Before compiling, you should set DEVNAME to the name of the interface the sample program should bind to and DESTINATIONMAC_INITIALIZER to the destination device you want to try to send packets to.

    I actually got this output (after running the program with sudo), showing how a packet over 1500 B is rejected:

    Using interface: wlp2s0 (index: 3)
    Bound to interface: wlp2s0 (index: 3)
    Source MAC address: 00:16:ea:4a:bd:7e
    Destination MAC address: 9c:d2:1e:20:91:e5
    Packet OK errors (if any): Success
    Packet OK: sent 1514 bytes.
    Packet WRONG errors (if any): Message too long
    Packet WRONG: sent -1 bytes.
    

    The "ok" packets, when launching the sample program for three times, were correctly received by the destination device, while all the "wrong" ones were not: Wireshark capture screenshot

    Thank you very much in advance.

    • 735Tesla
      735Tesla about 5 years
      I used to maintain software that did a lot of 802.11 frame generation/injection on Linux and never ran into that issue. Could I see the relevant code?
    • es483
      es483 about 5 years
      @735Tesla Of course! I just updated the original question with a sample code, extracted from the original one, that you can compile with gcc and that it should reproduce the problem for raw sockets. For what concerns SOCK_DGRAM, instead, the packet is always sent, but it gets fragmented when the size exceeds 1500 B (it can be seen not through a direct error, but for instance when using Wireshark). Thank you very much in advance.
  • siyuan
    siyuan over 11 years
    There is already a squid server on my router now.
  • siyuan
    siyuan over 11 years
    Thank you! There is already a squid server on my router now. Suppose my company's proxy is proxy.com:85, we setup a squid 192.168.0.5:3128. Now, we can access Internet by setting proxy as 192.168.0.5:3128 or proxy.com:85. What I want is to access Internet without setting proxy, because some program can't set proxy, such as some online update.