Monday, November 21, 2011

Skyrim Launcher Doesn't Work - Launcher Restarts

Today, Skyrim suddenly decided to stop working. I would launch it, press the Play button (on the launcher window) and then just have it reload after asking for Administrator privileges.

If you have this problem, to fix this you have 2 options.

1. Run Directly from Game File
  1. Navigate to your Steam installation (By default C:\Program Files (x86)\Steam)
  2. Then goto the SteamApps\common\skyrim directory
  3. From here just run TESV.exe directly.
  4. If it's missing, goto option 2.
2. The game file TESV.exe or any other file is missing.
  1. In Steam, right click Skyrim
  2. Select Properties
  3. Goto Local Files tab
  4. Click "Verify Integrity of Game Cache"
  5. It should download all broken/missing files.
  6. This didn't seem to fix it for me first time. So if it still doesn't work, try doing this same fix it just one more time.

    Sunday, May 22, 2011

    Why Love Linux

    I started a new blog at whylovelinux.com a few days ago.

    The idea is to make a new post every day for a year, describing a reason why I love Linux. The result will be 365 reasons to love Linux.


    I will not be comparing Linux against anything else for the purpose of convincing people to prefer Linux over others. I’m just sharing those things Linux made possible which make my life easier or more pleasant. If I do happen to compare it against something, it would be purely to explain the idea I was developing at that point.

    Many of the things mentioned are also possible in other operating systems. Especially on other Unixes, but also in Windows when using the specific software. It doesn’t change the fact that having this on Linux makes me appreciate it any more. To give an example. I can use grep to search for a string through a list of files. Most (if not all) Unix operating systems have grep, and you can always install grep on Windows. Though, grep comes preinstalled with the distributions I use, and if you find a good use for grep, it’s is a good reason to give a thumbs-up to Linux. It made all this possible!

    So be sure to subscribe to whylovelinux.com and find a new reason to Love Linux every day!

    Friday, March 18, 2011

    Linux iBurst Connection Script

     I always do things to make my life easier, and one of the ways I achieve this is scripts to automate tasks or make them more informative/easy to use.

    One of these tasks is connecting to the internet on my iBurst connection at home. This is for the USB modem which uses PPPoE over an ethernet device emulated by the driver.

    Originally I had to use "pon iburst" to connect, then check /var/log/messages to ifconfig to see if and when I am connected. Over time I started scripting this and this post is the result of that script.

    It has matured quite a bit over the past few years. A list of features can be summarized as follows:

    1. When instructed to connect will invoke "pon " (for a configured peer).
    2. Shows connection progress using a zenity dialog.
    3. All important feedback like errors are reported via zenity message boxes.
    4. A successful connect is reported via Gnome's informational messages using notify-send. This is only if the notify-send command is available and you are logged into a Gnome session. The fallback is to use a zenity message box.
    5. The assigned IP address will be displayed in the message when connected successfully.
    6. If pppd dies it will fail the connection attempt immediately and report this.
    7. If the connection attempt remains for a long time without getting an IP address, it will be timed out after a configured amount of time.
    8. If the connection attempt fails for any reason it will ensure pppd exits and kill it if necessary.
    9. Connects and disconnects can be cancelled. Script will ensure pppd exits and kill it if necessary.
    10. When killing pppd the script will use increasing levels of aggressiveness to work around being interrupted by blocking processes.
    11. If a connection existed previously it will disconnect unless otherwise instructed with command line switches.
    12. Can reliably detect if an existing iBurst connection is already active.
    13. Can be instructed to connect quietly.
    14. If the iBurst device isn't plugged into it will display an error.
    15. This error can be suppressed by a command line switch (useful in automation like if executed when you log in).
    16. Supports hooks for pre and post connect, successful disconnect and any error.
    17. Thorough logging to a configured log file.
    18. When executed as a non-root user will wrap itself inside a sudo session. This way if the sudo is configured to allow execution of the script without a password, then you can run the script as any of the allowed users.
    19. Automatically controls the up/down state of the iBurst driver interface (usually ib0). This was discovered from experience and experimentation and increases stability and maximum success with connection attempts. 
    20. Some misc other stability and reliability tweaks in the way connections are managed.
    This is quiet an extensive list of features. I have found the script to be very reliable these days and can probably say that I connect successfully 100% of the time. The only times I have problems is when the ISP has delays in authenticating me. I haven't had any problems in the past few months where I need to manually play around with plugging/unplugging the device, up/downing the interface, etc.

    So I decided to share it.

    How to Use
    Requirements to use it:
    1. Have zenity installed: apt-get install zenity
    2. If using Gnome, recommended to have notify-send installed: apt-get install libnotify-bin
    3. Have a PPPD peer setup that can be connected using: /usr/bin/pon peername
    4. Download the script at: http://sites.google.com/site/qbeukesblog/connect.iburst.sh
    With the above requirements satisfied you can edit the script and change the configuration options in the beginning. Most important option is the IB_IFACE and PEER variables. PEER should be the name of the peer used supplied to /usr/bin/pon. IB_IFACE should be the network device name created by the iBurst driver. This is usually ib0.

    Then if you're going to execute this command as a non-root user, add the following to your /etc/sudoers file. Remember to replace in your username and the full path to the connect script.
    your-username ALL=(root) NOPASSWD: /opt/iburst/connect.iburst.sh

    After this you can simply use the following commands to use the script. These commands assume the script is on the command path.

    Connect to the configured peer. Will disconnect if there is already an active connection:
    connect.iburst.sh

    Connect to the configured peer. If already connected will do nothing.
    connect.iburst.sh --no-disconnect

    Only attempt a connection if the iBurst device is plugged in. This is detected by checking if the IB_IFACE interface is available.
    connect.iburst.sh --conditional

    Only attempt a connection if the iBurst device is plugged in. Also, if already connecting nothing will be done.
    connect.iburst.sh --no-disconnect --conditional

    Hooks

    If you want to use the hooks, you need to create a directory called connect.iburst.hooks in the same location the script is executed from. So if you execute the script from /opt/iburst, you need to create the directory at /opt/iburst/connect.burst.hooks. If you want to put the directory in a different location, you can do so by editing the HOOKS_DIR variable in the beginning of the script.

    From here you can create hooks for 4 types of events:
    1. before: Pre Connect
    2. disconnect: Successful disconnect. Hooks receives 1 argument, which is the trigger for the disconnect.
    3. success: Post Successful Connect. Hooks receives 1 argument, which is the IP address.
    4. error: Error condition
    The files inside the hooks directory need to be named as follows:
    hookid.eventname.sh

    Here hookid is simply a name to identify the hook. You can choose this name and it may be anything valid in a filename. 

    The eventname is the name of one of the 4 hook events, as listed above (before, disconnect, success or error).

    Finally you just need the .sh extension.

    As a note, for any given event, these hooks are executed in no specific order. They are also executed synchronously, so any commands that won't exit needs to be executed in the background manually.

    Then, for the hook to be executed the file needs to be executable. 

    For an example, if we wanted to make a hook that will execute a dynamic DNS update whenever we are connected successfully, we would want to hook into the success event, so we'd call the script dynamicdns.success.sh.

    The success event supplies 1 argument to the script, which is the IP address we were assigned. We could then make use of this IP address when doing the DNS update. 

    Example Setup

    In my setup, I have the script and it's hooks installed at /usr/zbin/connect.iburst.sh and /usr/zbin/connect.iburst.hooks.

    Then I have the script configured in my sudoers file so I can execute it without a password.

    When I log into Gnome, on my panel I have a shortcut icon the I can click to connect explicitly. This will execute /usr/zbin/connect.iburst.sh. This way it will disconnect if it's already connected.

    Finally I also added a command to my Gnome startup, so that whenever I log in and the iBurst device is plugged in a connection will be created. Further, if a connection already exists it won't disconnect and reconnect. This could be the case where I, for example, would log out and log back in for whatever reason. This is achieved by adding the following command line to startup:
    connect.iburst.sh --no-disconnect --conditional

    Download

    The script can be downloaded from here: http://sites.google.com/site/qbeukesblog/connect.iburst.sh

    Saturday, December 25, 2010

    Draw Text and Shadows with GWTCanvas

    Overview
    This post will describe how to draw text and shadows with GWTCanvas.

    Example render of the HTML5Canvas widget (click image to enlarge):


    Introduction
    I started experimenting with HTML5 and GWT for a the user interface of a pet project I've been working on the last 2 years or so. At first I was using SVG through the Tatami GWT library, but decided to investigate the possibility of using the canvas.

    Unfortunately the standard GWT doesn't have widgets for interfacing with the HTML 5 canvas. The gwt-incubator project does have a GWTCanvas widget with basic support for the HTML5 canvas. Since the poor support of the <canvas> element in Internet Explorer, GWT emulates most of this. I figure this is the reason not all of the canvas API is provided via the GWTCanvas widget.

    One of the big missing features is the ability to draw text. One day, when Internet Explorer will support all of the canvas element, I'm sure the GWTCanvas will become much more functional.

    I am not targeting IE though. Being perfectly happy with Firefox and Google Chrome as a client, I want to be able to leverage all the canvas element's features, like shadows and drawing text. One day when IE implements it everything will hopefully fall in place. Not provided by the GWTCanvas I decided to extend it and provide these features.

    If you really need support for drawing text on Internet Explorer as well, you could possibly use the SWTB Canvas Font extension.

    Note that HTML5Canvas isn't an extension in the sense of extending the GWTCanvas widget class. Due  to the GWTCanvas class not exposing the canvas context JavaScriptObject, I had to copy the classes completely. I do use some of the classes that GWTCanvas depends on, and for this reason the gwt-incubator JAR is necessary on the classpath as well.  For convenience, I do supply all the necessary JARs on the SourceForge project.

    This extension was based on the version 20101117-r1766 of the gwt-incubator library for GWT 2.1.0.

    How to add the HTML5Canvas extension to your project
    1. Downloads the JARs at: https://sourceforge.net/projects/html5canvas/. Get both the gwt-incubator and html5canvas JAR.
    2. Add these JARs to your classpath.
    3. Add the following to your .gwt.xml file:
      <inherits name="com.blogspot.qbeukes.gwt.html5canvas.HTML5Canvas"/>
    4. You're ready to go!
    Using HTML5Canvas
    Creating the Widget
    You need to create an instance of com.blogspot.qbeukes.gwt.html5canvas.client.HTML5Canvas and add it to your display as you will add any other widget.

    Shadows
    Shadows are configured with these methods:
    public void setShadowBlur(double blur);
    public void setShadowColor(Color color);
    public void setShadowOffset(double x, double y);
    public void removeShadow();

    Then you can just stroke/fill and whatever you make visible will have a shadow.

    Example:
    canvas.saveContext();
    
    canvas.setShadowBlur(5);
    canvas.setShadowOffset(4, 4);
    canvas.setShadowColor(Color.BLACK);
    canvas.setFillStyle(Color.RED);
    canvas.fillRect(10, 20, 50, 50);
    canvas.removeShadow();
    
    canvas.setStrokeStyle(Color.BLACK);
    canvas.strokeRect(10, 20, 50, 50);
    
    canvas.restoreContext();

    Text
    To draw text you first need to create an instance of com.blogspot.qbeukes.gwt.html5canvas.client.Font. Through this class you can configure font family, size, variant, weight and all the CSS font properties available in HTML.

    From here you can use HTML5Canvas.setFont(Font) to configure it, and then use these methods to draw/configure text:
    public void fillText(String text, double x, double y);
    public void strokeText(String text, double x, double y);
    public double getTextWidth(String text);
    public void setTextBaseline(String textBaseline);
    public void setTextAlign(String textAlign);

    Font colors are configured with fill and stroke style, depending on which method you use to draw the font.

    Composite Operations
    Composite operation support is already available in GWTCanvas through setGlobalCompositeOperation(String), though there are only constants for destination-over and source-over.

    HTML5Canvas adds a new method, setGlobalCompositeOperation(com.blogspot.qbeukes.gwt.html5canvas.client.CompositeOp) and the CompositeOp enum used in the argument of this new method.

    The CompositeOp enum contains the following constants:
    CompositeOp.SOURCE_ATOP
    CompositeOp.SOURCE_IN
    CompositeOp.SOURCE_OUT
    CompositeOp.SOURCE_OVER
    CompositeOp.DESTINATION_ATOP
    CompositeOp.DESTINATION_IN
    CompositeOp.DESTINATION_OUT
    CompositeOp.DESTINATION_OVER
    CompositeOp.LIGHTER
    CompositeOp.COPY
    CompositeOp.XOR

    Demo/Examples
    For demo/examples, see com/blogspot/qbeukes/gwt/html5canvas/demo/HTML5CanvasDemo.java.

    This source file can be found
    1. Inside the HTML5Canvas JAR, or 
    2. Through Subversion from the SourceForge project under trunk/src/.
    You can also download the WAR from the SourceForge project and deploy this to a servlet container like Tomcat.

    Conclusion
    That's it. Enjoy.

    Friday, August 27, 2010

    Winning at Pick the Mug

    Everyone knows the classical Pick the Mug game, where you have 3 mugs and you have to guess which mug has the stone in it. Every time you play you have a 33% change to guess correctly.

    But what if, after you made your first guess, one of the other 2 mugs is revealed, specifically one that doesn't have the stone, and you have the option of changing your guess. In other words, if you were to pick mug A, and mug B had the stone, then mug C would be revealed and you can choose to either stay with mug A or change to mug B. Or for another example, if you choose mug B, and it has the stone, then either mug A or C would be revealed and you have the option of changing your option between your first choice and the one that wasn't revealed.

    If you were to stay with your choice, you still have only 33% chance to win. But if you were to change your choice, your chances to win increases to 66%. So if this were the rules of the game, you double your chances to win if you consistently change your choice.

    When I first heard this, I could understand the math behind it, but that's all I thought it was, a bit of math. I didn't think it would reflect the real world. In other words, I didn't think applying this would actually improve my chances of winning. After all, whether you stay or change, the designated mug didn't. I decided to put it to the test, and wrote a little program that will play the game a certain amount of rounds using each of the 2 strategies, and then see how effective each strategy was at winning.

    After doing this, and playing each strategy 1 million times, I found that the game was won 33% of the time when you stay with the initial choice, and 66% of the time if you change your choice. Here is the output of 5 games, each game being reseeded with the current time and all random number generation for a given game happening from the same java.security.SecureRandom instance.
    Playing 1000000 games with seed: 1282940127868
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.2673 |  332673 |
    | Change Guess  | 66.6309 |  666309 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282940139406
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3591 |  333591 |
    | Change Guess  | 66.5868 |  665868 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282940150963
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3038 |  333038 |
    | Change Guess  | 66.6906 |  666906 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282940162498
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3286 |  333286 |
    | Change Guess  | 66.6777 |  666777 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282940174009
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3406 |  333406 |
    | Change Guess  | 66.6462 |  666462 |
    + ------------- + ------- + ------- +
    

    There you have it. The amount of times won, consistently matches the statistical probabilities. I'm still battling to completely believe this, though the numbers show it does.

    Just as a fun test to compare java.security.SecureRandom with standard java.util.Random, I run 5 games with the standard Random, and the results seems to be pretty much the same.

    Here is the output using java.util.Random with 5 games:
    Playing 1000000 games with seed: 1282943227982
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3512 |  333512 |
    | Change Guess  | 66.6876 |  666876 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282943228344
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3279 |  333279 |
    | Change Guess  | 66.7352 |  667352 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282943228758
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.4019 |  334019 |
    | Change Guess  | 66.6114 |  666114 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282943229166
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3664 |  333664 |
    | Change Guess  | 66.6776 |  666776 |
    + ------------- + ------- + ------- +
    Playing 1000000 games with seed: 1282943229573
    + ------------- + ------- + ------- +
    | Description   | Perc    | Count   |
    + ------------- + ------- + ------- +
    | Keep Guess    | 33.3731 |  333731 |
    | Change Guess  | 66.6791 |  666791 |
    + ------------- + ------- + ------- +
    

    Random, as you can see from the seeds, was MUCH faster as well, all tests taking 2 seconds in total compared to 57 seconds with SecureRandom.

    To test if SecureRandom does give results generally closer to the probabilities, I decided to run 30 runs with 1,000,000 games on each run, and then see the deviations from 33.3% and 66.6% on each. Each game will be reseeded with the time on each run of 1,000,000 games. The results of this is:
    Playing 30 rounds with 1000000 games each.
    + --------------------- + ------- + ------- + ------- +
    | Description           | Min     | Max     | Range   |
    + --------------------- + ------- + ------- + ------- +
    | Secure Keep Guess     | 33.2524 | 33.4422 |  0.1898 |
    | Secure Change Guess   | 66.5545 | 66.7486 |  0.1941 |
    | Standard Keep Guess   | 33.2437 | 33.4309 |  0.1872 |
    | Standard Change Guess | 66.5841 | 66.7979 |  0.2138 |
    + --------------------- + ------- + ------- + ------- +
    

    So the results are actually pretty much the same. We're only randomizing between 2 and 3 after all. So there is no real conclusion here. Mostly just satisfied curiosity.

    You can download the application's code at: https://sites.google.com/site/qbeukesblog/MugsGame.tar.bz2. This is only the code for the initial tests. The experiments with the generators aren't included.

    Thursday, August 26, 2010

    Tunneling via SSH

    SSH is one of the most amazing protocols ever designed. OpenSSH's contributions to it makes it even more so. Whenever I set up a server, one of the first things I put in place is SSH access, because once you have SSH access to a server you can literally do almost anything. You can mirror drives, get past firewalls, fix software with connection/routing problems. The list is endless.

    Here I describe one of those amazing things you can do with SSH. Until I discovered this I was always doing port forwarding to communicate over SSH. This requires you to setup many ports if you need to forward something like NFS, for instance. With a tunnel you get a virtual ethernet device, with it's own IP address on each end. Then communication can happen on this device as if the two machines where physically connected. It's a VPN, using nothing more than an SSH connection.

    So in this description I have a server and a client. The server is a CentOS 5.4 machine, and the client an Ubuntu 10.04 machine.

    Client Setup
    Client probably has the more complex setup of the two. This is mainly because of the script that allows you to have more than one endpoint configured, and then select which at the time of bringing up the tunnel.

    If you have more than one endpoint in the script, this script only works when manually bringing up the tunnel from a terminal, since it will prompt you to which one to connect. If you wish to bring up the tunnel at system boot time this won't work, so you will need to copy the script for each tunnel you wish to bring up, and then list only one tunnel in each script, referencing the scripts in the correct interface configurations as needed.

    First things first. Generate the key pair. Navigate to /etc/ssh and run the following, entering tunnel_rsa for the key name:
    ssh-keygen -b 2048

    Then create the file /etc/ssh/tunnel-connect.sh, giving it the following contents:
    #!/bin/bash
    
    TARGET_LIST=(
      tunnel-host1.domain.com
      tunnel-host2.domain.com
    )
    
    function connect() 
    {
      local count=${#TARGET_LIST[@]}
      local nr desc target
    
      if [ $count -lt 1 ]
      then
        echo "No tunnel endpoints configured!" >&2
        exit 1
      elif [ $count -gt 1 ]
      then
        while true
        do
          echo "Tunnel Endpoints:" >&2
          for ((i=0; i<$count; i++)) {
            nr=$((i+1))
            desc=${TARGET_LIST[$i]}
      
            echo "  $nr. $desc" >&2
          }
      
          echo >&2
          read -p "Please enter number of endpoint to connect to (-1 to quit): " choice >&2
      
          # no choice
          if [ -z "$choice" ]
          then
            echo -e "\033[31mYou have to select a choice, or enter -1 to quit.\033[0m" >&2
            echo >&2
            continue
          fi
      
          # quit
          if [ "$choice" = "-1" ]
          then
            echo -e "\033[31mQuitting...\033[0m" >&2
            echo >&2
            exit 1
          fi
      
          # validate choice
          if [[ $choice = *[^0-9]* ]] || [ $choice -lt 1 -o $choice -gt $count ]
          then
            echo -e "\033[31mNot a valid choice '$choice'.\033[0m" >&2
            echo >&2
            continue
          fi
      
          target=${TARGET_LIST[$((choice-1))]}
          break
        done
      else
        target=${TARGET_LIST[0]}
      fi
      
      mkdir -p /var/run/sshd/tunnel-control
      ssh -M -f -S /var/run/sshd/tunnel-control/tun0 -i /etc/ssh/tunnel_rsa -w 0:0 root@$target true
      sleep 5
    }
      
    function disconnect()
    {
      ssh -S /var/run/sshd/tunnel-control/tun0 -O exit true
    }
    
    case "$1" in
      "--connect")
        connect
        ;;
    
      "--disconnect")
        disconnect
        ;;
    
      *)
        echo "Invalid option: $1" >&2
        echo "Valid options are --connect or --disconnect." >&2
        exit 1
    esac

    At the top of the script you can see a list of hosts in the TARGET_LIST variable. Remove the contents of the example, and enter the hostnames/IPs of the server host(s) you will be connecting to. If you have more than one host, the script will print a list of them and prompt which one to connect to. If you have only one host then it will automatically use that host.

    Give the script execute permissions:
    chmod a+x /etc/ssh/tunnel-connect.sh

    Finally, edit /etc/network/interfaces and add the following:
    iface tun0 inet static
    address 10.18.0.225
    pointopoint 10.18.0.1
    netmask 255.255.255.0
    pre-up /etc/ssh/tunnel-connect.sh --connect
    post-down /etc/ssh/tunnel-connect.sh --disconnect

    This will configure the tunnel to take on the IP address 10.18.0.225 for the client and 10.18.0.1 for the tunnel endpoint.

    Server Setup
    First we have to configure the tunnel device by creating a file /etc/sysconfig/network-scripts/ifcfg-tun0, assuming you have no previously configured tunnels. If you do, adapt the device names appropriately. The contents of the file is as follows:
    NAME="SSH Tunnel Device"
    DEVICE=tun0
    IPADDR=10.18.0.1
    NETMASK=255.255.255.0
    ONBOOT=no
    BOOTPROTO=none
    PEERDNS=no

    Here we configure a device named tun0 with IP address 10.18.0.1. It's also instructed to not load at boot time, and given a friendly name.

    Then, edit /etc/ssh/sshd_config and enable root login with the forced-commands-only option. You have to enable root login, since it's needed to bring up the tunnel interface. On top of this the PermitTunnel option must be set to yes. If you're using the AllowUsers option, remember to ensure the root username is listed in it as well. Your sshd configuration should have these 2 options afterwards:
    PermitRootLogin forced-commands-only
    PermitTunnel yes

    Finally, put the contents of the public key generated on the client (/etc/ssh/tunnel_rsa.pub) into /root/.ssh/authorized_keys, with the forced-commands options prepended to it, so it looks something like this
    command="/sbin/ifdown tun0; /sbin/ifup tun0",no-port-forwarding,no-pty,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAAB3...mNc= user@client-hostname

    The part from ssh-rsa onwards is the public key you generated.

    If you created the authorized_keys file, ensure the ownership and permissions of the /root/.ssh directory and it's contents are correct. Safe bet is to just run:
    chown -R root:root /root/.ssh
    chmod -R og-rwx /root/.ssh

    Setup the Firewall
    Update your firewall on both the server and client. Something like the following will allow all traffic to/from the tun0 interface. It's recommended to use this only for testing. Replace it with stricter rules once everything is working.
    iptables -I INPUT -i tun0 -j ACCEPT
    iptables -I OUTPUT -o tun0 -j ACCEPT

    Testing the Connection
    Back on the client, to connect the tunnel you can just run:
    ifup tun0

    If you have more than one destination server configured, you should be prompted to which server to connect.

    After the connection is established, you can test it by running this on the client:
    ping 10.18.0.1

    Now all communication that would normally have to go to the server, would just need to go to the 10.18.0.1 IP address. You can make this transparent by adding some clever NAT entries with iptables.

    To disconnect, run:
    ifdown tun0

    Example Usage of the Tunnel
    Say you're server is db-server with IP address 10.10.10.200, and it is running MySQL. If the MySQL port 3306 is closed on it's firewall, you can create a tunnel to the server, and then just connect to 10.18.0.1 for access to MySQL. Now you're past the firewall.

    But if you have software which is already configured, to avoid reconfiguring it everytime you try and test it, you have 2 options.

    If the software uses the hostname db-server instead of the IP itself, you can add an entry to /etc/hosts which maps the db-server hostname to the 10.18.0.1 IP address.

    If this isn't an option, you can also make the following DNAT entry:
    iptables -A OUTPUT -d 10.10.10.200 -p tcp -m tcp --dport 3306 -j DNAT --to-destination 10.18.0.1
    iptables -A POSTROUTING -o tun0 -j MASQUERADE

    This will now cause any traffic to 10.10.10.200 for port 3306/TCP to instead be instructed to goto 10.18.0.1. So the traffic is transparently rerouted via the tunnel.

    These rules will only work for traffic originating from the same machine as the one with the tunnel. If the machine with the tunnel is a gateway for other machines, then you can add the same rule above for the OUTPUT chain, to the PREROUTING chain as well, for example:
    iptables -A PREROUTING -d 10.10.10.200 -p tcp -m tcp --dport 3306 -j DNAT --to-destination 10.18.0.1

    There is so much you can do with this. For example if the tunnel endpoint does IPv4 packet forwarding, then you can setup a static route instead of a DNAT, and so forth. The power of this cannot be described in one sentence, let alone a thousand. Enjoy.

    And remember, with great power comes great hacks!

    Wednesday, August 11, 2010

    Cross Compiling OpenVPN for Windows on Linux

    I went through quite a struggle to build OpenVPN and a custom installer for Windows using my Linux machine. This post describes how to achieve this. To make it easier I packaged all the actual build steps into a script.

    This post works on the cross compiling environment prepared in my previous post Building a Cross Compiler on Linux for MinGW32.

    If you want to build the installer exe for OpenVPN as well, you will need NSIS (Nullsoft Installer System) installed. Download and compile it from http://nsis.sourceforge.net/.

    You will still be able to build the exes without NSIS. NSIS is only needed for packaging them into an installer.

    Also note that this doesn't build the TAP driver. It just copies the prebuilt one. To do this would have to install the Microsoft DDK, make an amd64 cross compile environment and modify my script to build the driver instead of copying it.

    First download the following:
    1. Prebuilt packages from http://openvpn.net/prebuilt/. Choose the latest -prebuilt .tbz file.
    2. Download the latest OpenVPN source code tar.gz archive.
    3. Download the build scripts from here.
    Then extract the build scripts to your home directory. This will then create a directory ~/openvpn-src which contains ~/openvpn-src/archive. Copy the prebuilt and OpenVPN source code packages into ~/openvpn-src/archive.

    Modify the ~/openvpn-src/env.sh script to reflect your cross-compiler environment. The variables have the following purposes:
    • PREFIX - Where to install the compiled OpenVPN files
    • TARGET - The build environment you're targeting, for example i686-mingw32msvc
    • TOOLCHAIN - The root location where the cross compiler binaries are access from.
    • MAKENSIS - The full path to your makensis variable. Leave this empty if you don't want the installer to be created or if you don't have NSIS installed.
    • The rest of them are standard autoconf environment variables.
    When you're ready you can kick of build-openvpn.sh.

    The resulting OpenVPN .exe files will be located in the directory your PREFIX variable points to, which by default would be ~/openvpn-dist.

    This script was tested with openvpn-2.1.1 and 2.1_rc22-prebuilt.tgz.