Back to Home

Udpxy on the provider's server

udpxy

Udpxy on the provider's server

    The wonderful udpxy utility has two features that you need to consider when using it in a carrier network.

    Firstly, the status and reset commands are available to all clients through a Web browser.

    Secondly, at about 40 simultaneous threads, udpxy starts to slow down, although the processor and network interface are almost not busy.


    Small digression


    As a rule, udpxy is not available as a binary package for the desired distribution, so it needs to be compiled from source.

    Clogging the working system with the packages necessary for assembly (compilers, libraries, utilities) is bad practice - the size of updates increases, dependencies become more complicated, etc.

    On the other hand, the organization of a separate assembly farm complicates the assembly, because requires synchronization of versions of working and assembly software, explicit indication of some parameters instead of automatically detecting, transferring assembled packages, etc.

    The compromise for a one-time assembly is to create a temporary assembly environment (“sandbox” aka “sandbox”) on the working system in a separate directory.

    In Debian Squeeze, the following commands are sufficient for this:
    apt-get install debootstrap
    mkdir /home/builder
    debootstrap squeeze /home/builder http://mirror.yandex.ru/debian
    chroot /home/builder apt-get update
    chroot /home/builder apt-get -y dist-upgrade
    chroot /home/builder apt-get -y install gcc make
    

    To build udpxy, you only need gcc and make; for larger programs, there may be more packages required.

    Assembly and installation


    Download the source archive and deploy it to the sandbox:
    ver="1.0.23-0"
    wget http://downloads.sourceforge.net/project/udpxy/udpxy/Chipmunk-1.0/udpxy.${ver}-prod.tar.gz'
    tar xzf ~/udpxy.${ver}-prod.tar.gz -C /home/builder/home/
    

    Change the names of the control teams to very secret ones:
    cd /home/builder/home/udpxy-${ver}
    sed -i.orig -e 's!/restart!/SECRET_restart!' -e 's!/status!/SECRET_status!' statpg.h
    sed -i.orig -e 's!"status"!"SECRET_status"!' -e 's!"restart"!"SECRET_restart"!' -e 's!"rtp"!"SECRET_rtp"!' extrn.c
    

    We go into the sandbox and compile:
    chroot /home/builder make -C /home/udpxy-${ver}
    

    We create a pseudo-user to run udpxy and a directory for the program and utilities, transfer the program to it:
    useradd --system --shell /bin/true --create-home udpxy
    install -o udpxy -g udpxy -m 700 -p /home/builder/home/udpxy-${ver}/udpxy /home/udpxy/
    


    Launch


    To increase the working limit of concurrent connections, we will start several udpxy instances on different ports and scatter requests coming to standard port 4022 on them, depending on the client IP address using iptables => nat => PREROUTING => REDIRECT:
    #!/bin/bash
    # /home/udpxy/start
    MAINPORT="4022"
    SUBPORTS="16"
     SUBMASK="40%02d"
      LOGDIR="/var/log/udpxy"
       UDPXY="/home/udpxy/udpxy"
        USER="udpxy"
    mkdir -p $LOGDIR || { echo "ERROR: cannot create $LOGDIR, aborted."; exit 1; }
    id "$USER" > /dev/null 2>&1 || { echo "ERROR: user $USER does not exists, aborted."; exit 1; }
    # Run instances and create redirects...
    for ((a = 0; a < "$SUBPORTS"; a++)); do
            p=`printf "$SUBMASK" "$a"`
            iptables -t nat -I PREROUTING -s 0.0.0.0/0.0.0.$a -p tcp -m tcp --dport "$MAINPORT" \
                    -j REDIRECT --to-ports "$p"
            while : ; do
                    date +"%Y.%m.%d %H:%M:%S -- Started $p"
                    sudo -u "$USER" "$UDPXY" -T -p $p -c32
                    date +"%Y.%m.%d %H:%M:%S -- Finished $p"
                    sleep 30
            done >> "$LOGDIR/$p.log" 2>&1 &
    done
    

    Explanations: firstly, the script requires bash, because sh does not understand the loop with the counter. Secondly, you cannot use “iptables -A” instead of “-I", because the rule with "-s 0.0.0.0/0.0.0.0" will be the first and will take all connections to itself. Third, the script continues to run in the background and automatically restarts completed (fallen?) Udpxy instances.

    By default, udpxy outputs a minimum of information to the /var/log/udpxy/*.log log files. If you want to make the output more detailed, add the "-v" and "-S" keys to the "sudo -u ..." launch line.

    Additional pens for which it makes sense to twist: "-B 1Mb" to increase the input buffer (in bytes), "-R 10" - the simultaneous number of messages (in pieces) and "-H 5" - maximum data buffering time (in seconds).

    Add challenge/ home / udpxy / start in /etc/rc.local (we will postpone scripting for /etc/init.d for another time).

    The completion script should look something like this:
    #!/bin/bash
    # /home/udpxy/stop
    # Remove firewall rules...
    iptables-save \
    | grep -- "-p tcp -m tcp --dport 4022 -j REDIRECT --to-ports" \
    | sed 's/^-A/iptables -t nat -D/' \
    | sh -
    # Kill program instances...
    pkill -f "/home/udpxy/udpxy"
    sleep 5
    # Kill wrapper scripts...
    pkill -f "/home/udpxy/start"
    


    View Status


    See the general list of connections to all udpxy instances as follows:
    #!/usr/bin/perl
    #  /var/www/html/SECRET-udpxy-status.cgi
    use strict;
    use warnings;
    my $port0 = 4000;
    my $ports = 16;
    my $status_cmd = 'SECRET_status';
    my $title = "Udpxy summary status";
    my $hostname;
    ($hostname = $ENV{HTTP_HOST}) =~ s/:\d+$//;
    print "Content-type: text/html\n\n" if $ENV{REMOTE_ADDR};  # ..cgi-bin mode?
    print << "__HEAD__";
    
    
    $title

    $title

    __HEAD__ my %cnt; my $total = 0; my $style_copied; my $style_passed; for (my $p = $port0; $p < $port0 + $ports; $p++) { open F, "wget -q -O - http://localhost:$p/$status_cmd |"; while() { if ($style_copied and /<\/style>/) { $style_copied = 0; # ..style finished $style_passed = 1; print; } elsif (/
    PortProcess IDSourceDestinationThroughput

    Read Next