Showing posts with label networking. Show all posts
Showing posts with label networking. Show all posts

Thursday, September 17, 2009

openvpn over ipv6 patch

It's baaaack. :)

Thanks to the support from my employer as 20% project, I'm (back) working on openvpn support for ipv6 endpoints (aka udp6, tcp6).

You can find the initial re-release, over openvpn-2.1_rc19
(latest as of Sep'09) at:
, obviously available as a git repository but also as a patch
snapshots at:
I'm pretty happy with this release, it has passed my unittests for {loopback,remote}{udp,tcp}{4,6} and also -it's valgrind friendly ;)

Enjoy it ! ... I'll post it to openvpn-devel ~soon.


--
--Juanjo ; echo jAjo@goMoSgleP.com | sed 's/[SPAM]//g'

Friday, September 19, 2008

@Kirk McKursick's FreeBSD Internals course

I had the fortunate pleasure to attend Kirk McKursick's FreeBSD internals course, kindly $upported by Google Switzerland, my employer =).



reeBSD_internals_book.jpg


McKursick-May_the_source_be_with_you.jjo.jpg
May the source be with you ... `:-)


One interesting discussion I had with Kirk was about the behavior of zombie processes with respect to opened sockets and TCP data lingering: he stated that a process could be in zombie state while pushing the data ashes thru an already opened TCP socket ... something that I couldn't agree with, mainly because this would imply a high wait() "latency" in under a pkt loss/congestion scenario.

Linux even has a tcp_max_orphans sysctl explicitly there for this (man 7 tcp), anyhow I wanted to be sure about the behavior of Linux and xBSD, so I coded a quick&dirty test, see zocket.c and Makefile below.


Result: as expected, the sockets were orphaned after the process became zombie, and remained as is (FIN_WAIT1) independently from the process path to death =) (tested on Linux, FreeBSd and OpenBSD).

As a side note, was interesting to find that in Linux you can push a BPF down to filter the very data stream, but in FreeBSD you can only hook at the accept() syscall with another mechanism (man 9 accept_filter), this is somewhat 2-sided for Linux: cool that you can arbitrary filter the data stream, notso-cool that you can easily create a local DoS with this power :)

make && make test ## should do the magic:


  • zocket.c
    /*
    * zocket.c: connect a socket, block its data stream, write data @children:
    * show zombie and socket lifetime afterwards
    *
    * Author: JuanJo: jjo () google com
    * License: GPLv2+
    */

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #if __linux__
    #include <linux/filter.h>
    #endif

    /* quickie wrapper over syscall error checking */
    #define ERR_IF(cond) do { if(cond) { perror( #cond ); abort(); } } while (0)

    static int block_fromto(int sockfd, const struct sockaddr_in *sp,
    const struct sockaddr_in *dp)
    {
    #ifdef __linux__
    /*
    * Push a BPF into _this_ socket only, interesting enough
    * this seems to be a linux-only feature, BSD has this available
    * only at accept().
    */

    struct sock_filter bpf_blockme[]= {
    BPF_STMT(BPF_RET+BPF_K, 0), /* just accept 0 bytes ;) */
    };
    struct sock_fprog filter = {
    sizeof(bpf_blockme)/sizeof(*bpf_blockme), bpf_blockme,
    };

    ERR_IF(setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER,
    &filter, sizeof(filter))<0);
    #else /* assuming BSD: block at PF level */
    char cmd[1024];
    cmd[sizeof cmd-1]=0;
    snprintf(cmd, sizeof cmd-1,
    "echo block drop out inet proto tcp "
    "from %s port %d to %s port %d| pfctl -f-",
    /* leaking but effective ... */
    strdup(inet_ntoa(sp->sin_addr)), htons(sp->sin_port),
    strdup(inet_ntoa(dp->sin_addr)), htons(dp->sin_port));
    printf("====== configuring pf:\n+ %s\n", cmd);
    ERR_IF(system(cmd)<0);
    #endif
    return 0;
    }
    int main(int argc, const char *argv[]) {
    int sock;
    int pid;
    int syncpipe[2];
    unsigned n;
    char cmd[2048];
    struct sockaddr_in dest,me;

    #ifndef __linux__
    /* need to use /sbin/pfctl for blocking pkt stream if !linux */
    assert(getuid()==0);
    #endif
    if (argc != 3) {
    fprintf(stderr, "ERROR: Usage: %s <ip> <port>\n", argv[0]);
    exit(255);
    }
    dest.sin_family = AF_INET;
    ERR_IF( inet_aton(argv[1], &dest.sin_addr) == 0);
    dest.sin_port=htons(atoi(argv[2]));

    sock = socket(AF_INET, SOCK_STREAM, 0);
    ERR_IF(sock <0);
    ERR_IF(connect (sock, (struct sockaddr *)&dest, sizeof dest) < 0);
    n=sizeof me;
    getsockname(sock, (struct sockaddr *)&me, &n);

    /* unbuffer stdout */
    setbuf(stdout, NULL);
    /* block (output) data stream */
    block_fromto(sock, &me, &dest);
    pipe(syncpipe);
    for(n=3;n;n--) {
    switch(pid=fork()) {
    case 0:
    close(syncpipe[0]);
    write(sock, "1234567890", 10);
    _exit(0);
    case -1: ERR_IF(1);
    }
    }
    close(sock);
    /* sync to children death */
    read(syncpipe[0], NULL, 0);
    cmd[sizeof cmd -1]=0;
    snprintf(cmd, sizeof cmd -1,
    "ps -o pid,ppid,stat,command|egrep [z]ocket;"
    "netstat -tn|egrep '[.:]%d .*[.:]%d'",
    ntohs(me.sin_port), ntohs(dest.sin_port));
    /* this will show the zombies and the socket send-q (as netstat -tn) */
    printf("====== BEFORE wait() ======\n+ %s\n", cmd); system(cmd);
    while(wait(NULL)>0);
    /* obviously the zombies are gone, what about the (orphaned) socket ?*/
    printf("====== AFTER wait() ======\n+ %s\n", cmd); system(cmd);
    return 0;
    }

  • Makefile
    ## Makefile for zocket.c
    ## Tested on: Linux 2.6, FreeBSD 6.x(dragonfly), OpenBSD 4.3
    CFLAGS=-Wall -g
    T=zocket.bin.$(OS)
    DEST=10.255.255.1 111

    ## No portable (GNU,BSD) way of doing VAR=<output_from_shellcmd>, wrap
    ## them by invoking make again
    all:
    make OS=`uname -s` all_os
    test:
    make OS=`uname -s` test_os

    all_os: $(T)

    setup_pf:
    ## FreeBSD: dynload PF module
    -@test -x /sbin/kldload && \
    { /sbin/kldstat | egrep pf.ko || { kldload pf; sleep 1;};}
    ## Enable PF
    -@test -x /sbin/pfctl && \
    sudo /sbin/pfctl -e -f- </dev/null 2>/dev/null;exit 0

    test_os: all_os setup_pf
    @ulimit -c 0; [ $(OS) != Linux -a -x /usr/bin/sudo ] && SUDO=sudo;\
    exec $$SUDO ./$(T) $(DEST) | tee test.out.$(OS)

    $(T): zocket.c
    $(CC) $(CFLAGS) -o $(@) $(?)

    clean:
    rm -fv zocket.bin.*

    %.html: %
    c2html -s $(^)

  • Thursday, May 17, 2007

    Jugando con IPv6 (apto para todo IPv4-público ;)

    Dale ... festejemos el día de Internet usando lo que es y será su pegamento futuro: IPv6.
    Ingredientes: tan sólo 1 IP pública
    Resultado: estemmm ... exactamente 1208925819614629174706176 (2^80 ;) direcciones IPv6, las cuales han estado ahí desde hace tiempo esperándote :-P
    Para saborear más aún: end-to-end para las máquinas que quieras ... como en los buenos viejos tiempos, por ej. podrás hacer desde "afuera":
    ssh -6 flamanteIPv6_de_esa_PC_que_no_tiene_IP_publica


    El mecanismo se llama tunneling 6to4, está descripto por doquier, en particular yo escribí un mini artículo para el seminario de IPv6 que dimos en el 2005 en la UM.

    Podés probar usando mi script: ipv6-setup6to4.sh , el cual sólo muestra los comandos necesarios (es decir: inofensivo :-), por ejemplo con una dir. IPv4= 65.1.2.3 da como salida:

    bash$ ./ipv6-setup6to4.sh
    IP4_ADDR=65.1.2.3
    IP6TO4_PREF=2002:4101:203
    #check you allow ipv6 encap: iptables -I INPUT -p 41 -d 65.1.2.3
    ip tunnel add tun6to4 mode sit remote any local 65.1.2.3 ttl 64
    ip addr flush dev tun6to4 2>/dev/null
    ip link set dev tun6to4 up
    ip addr add 2002:4101:203::1/16 dev tun6to4
    ip route add ::/96 dev tun6to4
    ip route add 2000::/3 via ::192.88.99.1 dev tun6to4 metric 1
    #you may do something like: ip -6 addr add 2002:4101:203:0001::1/64 dev eth0

    #NOTHING done, use me as: ./ipv6/ipv6-setup6to4.sh |sudo sh -x


    Que lo disfrutes!