Example #1
0
static int
tunnelDnsHandler(int status, GethostbynameRequestPtr request)
{
    TunnelPtr tunnel = request->data;

    if(status <= 0) {
        tunnelError(tunnel, 504,
                    internAtomError(-status, 
                                    "Host %s lookup failed",
                                    atomString(tunnel->hostname)));
        return 1;
    }

    if(request->addr->string[0] == DNS_CNAME) {
        if(request->count > 10)
            tunnelError(tunnel, 504, internAtom("CNAME loop"));
        do_gethostbyname(request->addr->string + 1, request->count + 1,
                         tunnelDnsHandler, tunnel);
        return 1;
    }

    do_connect(retainAtom(request->addr), 0,
               parentHost ? parentPort : tunnel->port,
               tunnelConnectionHandler, tunnel);
    return 1;
}
Example #2
0
/* PSIPHON: entire function */
static int
tunnelSplitTunnelingDnsHandler(int status, GethostbynameRequestPtr request)
{
    TunnelPtr tunnel = request->data;

    if(status <= 0) {
        tunnelError(tunnel, 504,
                    internAtomError(-status,
                                    "Host %s lookup failed",
                                    atomString(tunnel->hostname)));
        return 1;
    }

    if(request->addr->string[0] == DNS_CNAME) {
        if(request->count > 10)
            tunnelError(tunnel, 504, internAtom("CNAME loop"));
        do_gethostbyname_socks(request->addr->string + 1, request->count + 1,
                         tunnelSplitTunnelingDnsHandler, tunnel);
        return 1;
    }

    //Get IP from the request, check against our local networks list
    int local_addr = 0;
    if(request->addr->string[0] == DNS_A)
    {
        HostAddressPtr host_addr;
        host_addr = (HostAddressPtr) &request->addr->string[1];
        //we deal only with IPv4 addresses
        if(host_addr->af == 4)
        {
            struct in_addr servaddr;
            memcpy(&servaddr.s_addr, &host_addr->data, sizeof(struct in_addr));
            local_addr =  isLocalAddress(servaddr);
        }
    }

    if (local_addr != 0)
    {
        printf("PSIPHON-UNPROXIED:>>%s<<", request->name->string);
        fflush(NULL);
    }

    //Use SOCKS for IPs that are not local and connect directly to the ones that are
    //At this point the DNS record for the request should be cached, default TTL for DNS requests
    //is 240 seconds
    if(local_addr == 0)
    {
            do_socks_connect(parentHost ?
                    parentHost->string : tunnel->hostname->string,
                    parentHost ? parentPort : tunnel->port,
                    tunnelSocksHandler, tunnel);
    }
    else
    {
        do_connect(retainAtom(request->addr), 0,
                parentHost ? parentPort : tunnel->port,
                tunnelConnectionHandler, tunnel);
    }
    return 1;
}
Example #3
0
static int
tunnelSocksHandler(int status, SocksRequestPtr request)
{
    TunnelPtr tunnel = request->data;

    if(status < 0) {
        tunnelError(tunnel, 504, internAtomError(-status, "Couldn't connect"));
        return 1;
    }

    return tunnelHandlerCommon(request->fd, tunnel);
}
Example #4
0
static int
tunnelConnectionHandler(int status,
                        FdEventHandlerPtr event,
                        ConnectRequestPtr request)
{
    TunnelPtr tunnel = request->data;
    int rc;

    if(status < 0) {
        tunnelError(tunnel, 504, internAtomError(-status, "Couldn't connect"));
        return 1;
    }

    rc = setNodelay(request->fd, 1);
    if(rc < 0)
        do_log_error(L_WARN, errno, "Couldn't disable Nagle's algorithm");

    return tunnelHandlerCommon(request->fd, tunnel);
}
Example #5
0
static int
tunnelHandlerParent(int fd, TunnelPtr tunnel)
{
    char *message;
    int n;

    if(tunnel->buf1.buf == NULL)
        tunnel->buf1.buf = get_chunk();
    if(tunnel->buf1.buf == NULL) {
        message = "Couldn't allocate buffer";
        goto fail;
    }
    if(tunnel->buf1.tail != tunnel->buf1.head) {
        message = "Pipelined connect to parent proxy not implemented";
        goto fail;
    }

    n = snnprintf(tunnel->buf1.buf, tunnel->buf1.tail, CHUNK_SIZE,
                  "CONNECT %s:%d HTTP/1.1",
                  tunnel->hostname->string, tunnel->port);
    if (parentAuthCredentials)
        n = buildServerAuthHeaders(tunnel->buf1.buf, n, CHUNK_SIZE,
                                   parentAuthCredentials);
    n = snnprintf(tunnel->buf1.buf, n, CHUNK_SIZE, "\r\n\r\n");

    if(n < 0) {
        message = "Buffer overflow";
        goto fail;
    }
    tunnel->buf1.head = n;
    tunnelDispatch(tunnel);
    return 1;

 fail:
    CLOSE(fd);
    tunnel->fd2 = -1;
    tunnelError(tunnel, 501, internAtom(message));
    return 1;
}
Example #6
0
static int
tunnelHandlerCommon(int fd, TunnelPtr tunnel)
{
    const char *message = "HTTP/1.1 200 Tunnel established\r\n\r\n";

    tunnel->fd2 = fd;

    if(parentHost)
        return tunnelHandlerParent(fd, tunnel);

    if(tunnel->buf2.buf == NULL)
        tunnel->buf2.buf = get_chunk();
    if(tunnel->buf2.buf == NULL) {
        CLOSE(fd);
        tunnelError(tunnel, 501, internAtom("Couldn't allocate buffer"));
        return 1;
    }

    memcpy(tunnel->buf2.buf, message, MIN(CHUNK_SIZE - 1, strlen(message)));
    tunnel->buf2.head = MIN(CHUNK_SIZE - 1, strlen(message));

    tunnelDispatch(tunnel);
    return 1;
}
Example #7
0
void 
do_tunnel(int fd, char *buf, int offset, int len, AtomPtr url)
{
    TunnelPtr tunnel;
    int port;
    char *p, *q;

    tunnel = makeTunnel(fd, buf, offset, len);
    if(tunnel == NULL) {
        do_log(L_ERROR, "Couldn't allocate tunnel.\n");
        releaseAtom(url);
        dispose_chunk(buf);
        CLOSE(fd);
        return;
    }

    if(proxyOffline) {
        do_log(L_INFO, "Attemted CONNECT when disconnected.\n");
        releaseAtom(url);
        tunnelError(tunnel, 502,
                    internAtom("Cannot CONNECT when disconnected."));
        return;
    }

    p = memrchr(url->string, ':', url->length);
    q = NULL;
    if(p)
        port = strtol(p + 1, &q, 10);
    if(!p || q != url->string + url->length) {
        do_log(L_ERROR, "Couldn't parse CONNECT.\n");
        releaseAtom(url);
        tunnelError(tunnel, 400, internAtom("Couldn't parse CONNECT"));
        return;
    }
    tunnel->hostname = internAtomLowerN(url->string, p - url->string);
    if(tunnel->hostname == NULL) {
        releaseAtom(url);
        tunnelError(tunnel, 501, internAtom("Couldn't allocate hostname"));
        return;
    }

    if(!intListMember(port, tunnelAllowedPorts)) {
        releaseAtom(url);
        tunnelError(tunnel, 403, internAtom("Forbidden port"));
        return;
    }
    tunnel->port = port;
    
    if (tunnelIsMatched(url->string, url->length, 
			tunnel->hostname->string, tunnel->hostname->length)) {
        releaseAtom(url);
        tunnelError(tunnel, 404, internAtom("Forbidden tunnel"));
	logTunnel(tunnel,1);
        return;
    }
    
    logTunnel(tunnel,0);
    
    releaseAtom(url);

    if(socksParentProxy)
        do_socks_connect(parentHost ?
                         parentHost->string : tunnel->hostname->string,
                         parentHost ? parentPort : tunnel->port,
                         tunnelSocksHandler, tunnel);
    else
        do_gethostbyname(parentHost ?
                         parentHost->string : tunnel->hostname->string, 0,
                         tunnelDnsHandler, tunnel);
}
Example #8
0
void
do_tunnel(int fd, char *buf, int offset, int len, AtomPtr url)
{
    TunnelPtr tunnel;
    int port;
    char *p, *q;

    /* PSIPHON */
    if(psiphonStats)
    {
        /* Update the page view stats by printf-ing the URI. Our stdout is piped to
           the client process. */
        printf("PSIPHON-PAGE-VIEW-HTTPS:>>%s<<\n", url->string);
        fflush(NULL);
    }
    /* /PSIPHON */

    tunnel = makeTunnel(fd, buf, offset, len);
    if(tunnel == NULL) {
        do_log(L_ERROR, "Couldn't allocate tunnel.\n");
        releaseAtom(url);
        dispose_chunk(buf);
        CLOSE(fd);
        return;
    }

    if(proxyOffline) {
        do_log(L_INFO, "Attemted CONNECT when disconnected.\n");
        releaseAtom(url);
        tunnelError(tunnel, 502,
                    internAtom("Cannot CONNECT when disconnected."));
        return;
    }

    p = memrchr(url->string, ':', url->length);
    q = NULL;
    if(p)
        port = strtol(p + 1, &q, 10);
    if(!p || q != url->string + url->length) {
        do_log(L_ERROR, "Couldn't parse CONNECT.\n");
        releaseAtom(url);
        tunnelError(tunnel, 400, internAtom("Couldn't parse CONNECT"));
        return;
    }
    tunnel->hostname = internAtomLowerN(url->string, p - url->string);
    if(tunnel->hostname == NULL) {
        releaseAtom(url);
        tunnelError(tunnel, 501, internAtom("Couldn't allocate hostname"));
        return;
    }

    /* PSIPHON
       Checking if tunnel is allowed on a particular port is not needed if the
       proxy accepts connections made only from localhost */
    /*
    if(!intListMember(port, tunnelAllowedPorts)) {
        releaseAtom(url);
        tunnelError(tunnel, 403, internAtom("Forbidden port"));
        return;
    }
    */
    /* /PSIPHON */

    tunnel->port = port;

    if (tunnelIsMatched(url->string, url->length,
			tunnel->hostname->string, tunnel->hostname->length)) {
        releaseAtom(url);
        tunnelError(tunnel, 404, internAtom("Forbidden tunnel"));
	logTunnel(tunnel,1);
        return;
    }

    logTunnel(tunnel,0);

    releaseAtom(url);

    /* PSIPHON split tunneling option*/
    /* This was the original:
    if(socksParentProxy)
        do_socks_connect(parentHost ?
                         parentHost->string : tunnel->hostname->string,
                         parentHost ? parentPort : tunnel->port,
                         tunnelSocksHandler, tunnel);
    */
    if(socksParentProxy) {
        if(splitTunneling)
        {
            do_gethostbyname_socks(parentHost ?
                    parentHost->string : tunnel->hostname->string, 0,
                    tunnelSplitTunnelingDnsHandler, tunnel);
        }
        else
        {
            do_socks_connect(parentHost ?
                    parentHost->string : tunnel->hostname->string,
                    parentHost ? parentPort : tunnel->port,
                    tunnelSocksHandler, tunnel);
        }
    }
    /* /PSIPHON */
    else
        do_gethostbyname(parentHost ?
                         parentHost->string : tunnel->hostname->string, 0,
                         tunnelDnsHandler, tunnel);
}