Running a graphical window program via SSH on a remote machine (with GPU hardware acceleration)

Note 1: Even though it’s mid-2018, this post is still about the X Window System. Things still are in the transition phase towards Wayland, and things might get better or different over time.

Note 2: This post is not about displaying a graphical window of a program running on a remote machine on the local machine (like VNC or X forwarding). It is about running a remote program and displaying its graphical window on the remote machine itself, as if it had been directly started by a user sitting in front of the remote display. One obvious use case for the solution to this problem would be a remote graphics rendering farm, where programs must make use of the GPU hardware acceleration of the machine they’re running on.

Note that graphical programs started via Xvfb or via X login sessions on fake/software displays (started by some VNC servers) will not use GPU hardware acceleration. The project VirtualGL might be a viable solution too, but I haven’t looked into that yet.

Some experiments on localhost

I’m going to explore the behavior of localhost relative to our problem first. You’ll  need to be logged in to an X graphical environment with monitor attached.

The trivial case: No SSH login session

Running a local program with a graphical window from a local terminal on a local machine is trivial when you are logged into the graphical environment: For example, in a terminal, simply type glxgears and it will run and display with GPU hardware acceleration.

With SSH login session to the same user

Things become a bit more interesting when you use SSH to connect to your current user on localhost. Let’s say your local username is “me”. Try

It will output:

This can be fixed by setting the DISPLAY variable to the same value that is set for the non-SSH session:

Glxgears will run at this point.

With SSH login session to another user

Things become even more interesting when you SSH into some other local user on localhost, called “other” below.

You will get the message:

Trying to export DISPLAY as before won’t help us now:

You will receive the message:

This is now a permission problem. There are two solutions for it:

Solution 1: Relax permissions vIA XHOST PROGRAM

To allow non-networked connections to the X server, you can run (as user “me” which is currently using the X environment):

Then DISPLAY=:0 glxgears will start working as user “other”.

For security reasons, you should undo what you just did:

Settings via xhost are not permanent across reboots.

Solution 2: via Xauthority file

If you don’t want or can’t use the xhost program, there is a second way (which I like better because it only involves files and file permissions):

User “me” has an environment variable  env | grep XAUTHORITY

(I’m using the gdm display manager. The path could be different in your case.)

This file contains a secret which is readable only for user “me”, for security reasons. As a quick test, make this file available world-readable in /tmp:

Then, as user “other”:

Glxgears will run again.

To make sure that we are using hardware acceleration, run glxinfo:

This prints for me:

Make sure you remove  /tmp/xauthority_me after this test.

Note that the Xauthority file is different after each reboot. But it should be trivial to make it available to other users in a secure way if done properly.

Application on remote machine

If you were able to make things work on the local machine, the same steps should work on a remote machine, too. To clarify, the remote machine needs:

  • A real X login session active (you will likely need to set up auto-login in your display manager if the machine is not accessible).
  • A real monitor attached. Modern graphics cards and/or BIOSes simply shut down the GPU to save power when there is no real device attached to the HDMI port. This is is not Linux or driver specific. Instead of real monitors, you probably want to use “HDMI emulator” hardware plugs – they are cheap-ish and small. Otherwise, the graphical window might not even get painted into the graphics memory. The usual symptom is a black screen when using VNC.

Summary

If you SSH-login into the remote machine, as the user that is currently logged in to the X graphical environment, you can just set the DISPLAY environment variable when running a program, and the program should show on the screen.

If you SSH-login into the remote machine, as a user that is not currently logged in to the X graphical environment, but some other user is, you can set both DISPLAY and XAUTHORITY environment variables as explained further above, and the program should show up on the screen.

Related Links

https://serverfault.com/questions/186805/remote-offscreen-rendering

https://stackoverflow.com/questions/6281998/can-i-run-glu-opengl-on-a-headless-server#8961649

https://superuser.com/questions/305220/issue-with-vnc-when-there-is-no-monitor

https://askubuntu.com/questions/453109/add-fake-display-when-no-monitor-is-plugged-in

https://software.intel.com/en-us/forums/intel-business-client-software-development/topic/279956

Simple test if TCP port is open

There are other more complicated tools to achieve the same (like nmap whose manpage makes your head spin), but this is a very simple solution using netcat:

To programmatically evaluate the result, use the standard Bash $? variable. It will be set to 0 if the port was open, or 1 if the port was closed.

Zero Client: Boot kernel and root filesystem from network with a Raspberry Pi2 or Pi3

Boot your Raspberry Pi from nothing but an Ethernet cable

A Zero Client is a computer that has nothing on its permanent storage but a bootloader. Rather, it loads everything from the network.

With the method presented in this article, you will be able to boot a Raspberry Pi into a full Debian OS with nothing more on the SD card other than the Raspberry firmware files and the u-boot bootloader on a FAT file system. The Linux kernel and the actual OS will be served over the local ethernet network.

We will only focus on the Raspberry Pi 3, but the instructions should work with minor adaptations also on a Pi 2.

The following instructions assume that you have already built…

  1. a full root file system for the Raspberry
  2. a u-boot binary, and
  3. a Linux kernel

… based on my previous blog post. Thus, you should already have the following directory structure:

We will do all the work inside of the ~/workspace directory.

Preparation of the SD card

You will only need a small SD card with a FAT filesystem on it. The actual storage of files in the running OS will be transparently done over the network. Mount the filesystem on /mnt/sdcard and do the following:

Copy firmware

Copy u-boot bootloader

Create config.txt

config.txt is the configuration file read by the Raspberry firmware blobs. Most importantly, it tells the firmware what kernel to load. “Kernel” is a misleading term here, since we will boot u-boot rather than the kernel.

Create /mnt/sdcard/config.txt with the following contents:

 

Make an universal boot script for the u-boot bootloader

To achieve maximum flexibility — to avoid the repetitive dance of manually removing the SD card, copying files to it, and re-inserting it — we will make an universal u-boot startup script that does nothing else than loading yet another u-boot script from the network. This way, there is nothing specific about the to-be-loaded Kernel or OS on the SD card at all.

Create a file boot.scr.mkimage  with the following contents:

Replace the server IP with the actual static IP of your server. Note that this script does nothing else other than loading yet another script called netboot-${serial#}.scr  from the server. serial# is the serial number which u-boot extracts from the Raspberry Pi hardware. This is usually the ethernet network device HW address. This way, you can have separate startup scripts for several Raspberry Pi’s if you have more than one. To keep the setup simple, set the file name to something predictable.

Compile the script into an u-boot readable image:

Copy boot.scr to the SD card:

The SD card preparation is complete at this point. We will now focus on the serving of the files necessary for boot.

Preparation of the file server

Do all of the following as ‘root’ user on a regular PC running Debian 9 (“Stretch”). This PC will act as the “server”.  This server will serve the files necessary to network-boot the Raspberry.

The directory /srv/tftp will hold …

  • an u-boot start script file
  • the kernel uImage file
  • and the binary device tree file.

… to be served by a TFTP server.

The directory /srv/rootfs_rpi3 will hold our entire root file system to be served by a NFS server:

You will find installation instructions of both TFTP and NFS servers further down.

 

Serve the root file system

Let’s copy the pre-built root file system into the directory from where it will be served by the NFS server:

(notice the slash at the end of the source directory)

 

Fix the root file system for network booting

Edit  /srv/rootfs_rpi3/etc/fstab  and comment out all lines. We don’t need to mount anything from the SD card.

When network-booting the Linux kernel, the kernel will configure the network device for us (either with a static IP or DHCP). Any userspace programs attempting to re-configure the network device will cause problems, i.e. a loss of conncection to the NFS server. Thus, we need to prevent systemd-networkd from managing the Ethernet device. Make the device unmanaged by removing the folowing ethernet configuration file:

If you don’t do that, you’ll get the following kernel message during boot:

That is because systemd has shut down and then re-started the ethernet device. Apparently NFS transfers are sensitive to that.

In case you want to log into the chroot to make additional changes that can only be done from within (e.g. running systemctl scripts etc.), you can do:

 

Serve Kernel uImage

In this step, we create a Linux kernel uImage that can be directly read by the u-boot bootloader. We read Image.gz directly from the Kernel source directory, and output it into the /srv/tftp directory where a TFTP server will serve it to the Raspberry:

 

Serve device tree binary

The u-boot bootloader will also need to load the device tree binary and pass it to the Linux kernel, so copy that too into the /srv/tftp directory.

 

Serve secondary u-boot script loading the kernel

Create a file netboot-rpi3.scr.mkimage with the following contents:

Replace the server IP with the static IP of your server PC. Then compile this script into an u-boot readable image and output it directly to the /srv/tftp directory:

Make sure that the filename of the .scr file matches with whatever file name you’ve set in the universal .scr script that we’ve prepared further above.

 

Install a NFS server

The NFS server will serve the root file system to the Raspberry and provide transparent storage.

Edit /etc/exports and add:

To apply the changed ‘exports’ configuration, run

Useful to know about the NFS server:

You can restart the NFS server by running service nfs-kernel-server restart

Configuration files are /etc/default/nfs-kernel-server  and /etc/default/nfs-common

 

Test NFS server

If you want to be sure that the NFS server works correctly, do the following on another PC:

Mount the root file system (fix the static IP for your server):

 

 

Install a TFTP server

To install:

After installation, check if the TFTP server is running:

This command will tell you the default serving directory (/srv/tftp):

Here is another command that tells you if the TFTP server is listening:

To get help about this server: man tftpd

Test TFTP

If you want to be sure that the TFTP server works correctly, do the following on another PC:

Then see if the server serves the Linux kernel we’ve installed before:

You now should have a local copy of the linux-rpi3.uImage file.

 

Complete

If you’ve done all of the above correctly, you can insert the prepared SD card into your Raspberry Pi and reboot it. The following will happen:

  1. The Raspberry Pi GPU will load the firmware blobs from the SD card.
  2. The firmware blobs will boot the image specified in config.txt. In our case, this is the u-boot binary on the SD card.
  3. The u-boot bootloader will boot.
  4. The u-boot bootloader loads and runs the universal boot.scr script from the SD card.
  5. The boot.scr downloads the specified secondary boot script from the network and runs it.
  6. The secondary boot script …
    • downloads the device tree binary from the network and loads it into memory.
    • downloads the Linux kernel from the network and loads it into memory
    • passes the device tree binary to the kernel, and boots the kernel
  7. the Linux kernel will bring up the ethernet device, connect to the NFS server, and load the regular OS from there.

Many things can go wrong in this rather long sequence, so if you run into trouble, check the Raspberry boot messages output on an attached screen or serial console, and the log files of the NFS and TFTP servers on your server PC.

 

Resources

https://www.raspberrypi.org/documentation/linux/kernel/building.md

http://www.whaleblubber.ca/boot-raspberry-pi-nfs/

https://cellux.github.io/articles/moving-to-nfs-root/

http://billauer.co.il/blog/2011/01/diskless-boot-nfs-cobbler/

https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt

http://wiki.linux-nfs.org/wiki/index.php/General_troubleshooting_recommendations

https://wiki.archlinux.org/index.php/NFS

How to turn the Raspberry Pi into a Gateway to mobile phone internet

Your DSL internet connection is too slow? Want to set up an improvised office? You do not want to pay for a DSL internet plan when you already have a fast 4G mobile plan? If yes to one of the above, it is quite easy to configure a Raspberry Pi to share one mobile internet connection to an Ethernet network.

raspberry pi mobile gateway topology
Turning a Raspberry Pi into a Gateway to mobile internet (Image license CC BY-SA 3.0)

Strictly speaking, you don’t have to use a Raspberry Pi to do this. A laptop or desktop computer with any Operating System would work too, but the Raspberry is so small and consumes only 2-3 W of electrical power, and is so cool (quite literally!), so will will make use of this awesomeness!

 

Prerequisites

The following step-by-step guide is based on a pure Debian 9 (“Stretch”) distribution with a mainline/vanilla/unpatched Linux kernel built according to my previous blog post:

Raspberry Pi2 and Pi3 running pure Debian 9 (“Stretch”) and the Linux Mainline/Vanilla Kernel

  • We will not focus on the Raspbian OS nor on any other distribution, because documentation for these other setups exists in abundance.
  • You should not have a graphical interface installed. GUIs also install the NetworkManager service for systemd (Debian package “network-manager”), and I have not tested how NetworkManager interacts with the methods presented below. In addition, a bare-bone system is the preferred choice because it saves RAM and CPU resources.
  • In any case, you should attach a keyboard and screen to the Raspberry because you may temporarily lose network connectivity during the setup.
  • You also need a smart phone with an internet plan, supporting USB tethering. I have only tested recent Android based smartphones. Keep in mind during the following steps that, with most smart phones, you need to re-enable USB tethering after reboots or USB cable reconnects.

 

Goals

  • Computers in the LAN will be able to set the Raspberry Pi’s static IP address as internet Gateway and DNS server.
  • The Raspberry Pi will prefer a smart phone connection (tethered USB) to forward traffic.
  • If the smart phone is disconnected, the Rasbperry Pi will automatically fall back to an already existing gateway if present (i.e. a DSL modem)

 

Step 1: Install a DNS server

This ensures that cached DNS lookups are very fast when a DNS query has already been fetched.

Tell “bind” to use Google’s public DNS servers (they are good). Edit /etc/bind/named.conf.options and change the “forward” block to:

Restart “bind”:

 

Step 2: Configure a static IP address for the Ethernet adapter

If you already have a DHCP server running in your local network (we will use the subnet 192.168.0.0 in this guide), give the Raspberry Pi a free static IP address in this existing subnet, e.g. 192.168.0.250.

If you don’t have an existing DHCP server running in your local network, we will set one up on the Raspberry (see Step 8 below).

In both cases, we will give our Rasberry the static IP address 192.168.0.250. Using systemd, change the config file of your ethernet connection /etc/systemd/network/eth.network:

 

If your LAN already has an internet gateway, e.g. a DSL modem with address 192.168.0.1, add the following (optional) section to the same config file:

The large positive integer value of “Metric” ensures that other configured gateways with a lower Metric will be preferred. This will come in handy in the next step where the smart phone will be our preferred gateway with a Metric value of 1024.

Now reboot the Raspberry or run systemctl restart systemd-networkd.  You may lose network connectivity at this point if you are logged in via ssh.

Now, check that networkctl status eth0 matches our wanted static IP address:

Next, check the output of route -n (the kernel routing table). It should show:

If you have added the optional  [Route] section, you should also see the following as first line, which is our current default route to the internet:

 

 

Step 3: Set the smart phone connection as gateway

Plug in your phone’s USB cable into one of the Raspberry’s USB connectors. Then turn on USB tethering in the Settings UI of your smart phone.

Run networkctl. You should see the following entry amongst the other network connections (notice “off” and “unmanaged”).

 

To have the “systemd-networkd” service manage the “usb0” network device, create a file /etc/systemd/network/mobile.network with the following contents:

To apply this config file, run systemctl restart systemd-networkd .  After a few seconds,  networkctl should output (notice the “routable” and “configured” parts):

You also can check networkctl status usb0  to see the dynamic IP address obtained from the DHCP server on the smart phone. For Android phones this is usually in the subnet 42.

Next, check the output of route -n. Now, the phone connection “usb0” should be on the top of the list thanks to the lower metric of 1024:

 

Step 4: Check internet connectivity

With this routing table, we already can connect to the internet via the smart phone. To make sure that we are routed via the smart phone, we will ask the Linux kernel which gateway it would take first for traffic. ip route get 8.8.8.8  should ouput the IP address of the smart phone (192.168.42.129, subnet 42):

Let’s ping Google’s server a few times: ping 8.8.8.8  to see if we have an actual working route to the internet:

The answer: Yes!

Check phone’s DNS server

 

Now let’s check if the phone’s DNS server is working. Type  dig google.com (install Debian package “dnsutils” if not yet installed), and make sure that you’ve got an “ANSWER SECTION”:

Note that the response came from the phone’s IP. So, “systemd” has correctly configured the phone’s IP address as DNS server for the Raspberry (that information came from the phone’s DHCP server).

Run  dig google.com again. This time the result should be cached and returned much faster (just 1ms):

Check local DNS server

Type  dig @localhost google.com:

Note that this time, the response came from the “bind” DNS server which we have installed in Step 1. It, in turn, forwards queries via the phone connection. This server will be used for all requests via Ethernet.

Step 5: Turn on IP protocol forwarding for the Linux kernel

By default, this feature is turned off. Check the current status of this feature:

sysctl -a | grep net\.ipv4\.ip_forward  will output:

To permanently set this variable to 1, create /etc/sysctl.d/30-ipforward.conf and add the following:

Reload all settings by typing  sysctl --system. Now, and also after a reboot, the “ip_forward” variable should stay enabled.

 

Step 6: Turn on Network address translation (NAT) aka. “Masquerading” between Ethernet and USB Smart Phone network links

Create a shell script  /usr/bin/startgateway.sh with the following contents and make it executable ( chmod a+x):

This will masquerade IP packets coming in through the Ethernet adapter as if they were coming from the Raspberry itself, forward them to the USB smart phone connection, and the incoming answers (from remote servers) will be re-written and forwarded back to whereever in the LAN they came from. That is the central purpose of the problem we’re trying to solve in this tutorial.

Run this script. Check the output of iptables -L -n -v:

 

To run this shell script at system boot, right after the network links have been brought up, create the following systemd service file:

Add the following:

 

 

Step 7: Test the Raspberry Gateway!

On another machine in your LAN (can be Linux, Windows or Mac), configure the Ethernet connection manually. Set the following:

  • Static IP Address: 192.168.0.10 (or any other freely available address on this subnet)
  • Gateway: 192.168.0.250
  • DNS: 192.168.0.250

Then run traceroute 8.8.8.8  on that other machine. Truncated output:

The route is correctly resolved. First traffic goes to the Raspberry Pi, then to the smart phone, and from there to the internet.

If you can’t run traceroute on that other machine, using a regular browser to browse the internet should work at this point!

 

Step 8: Running a DHCP server on the Raspberry

TODO

 

Conclusion

This tutorial may seem long, but the commands are few, and with a bit of practice you can turn your Raspberry Pi into a mobile phone Gateway in 10 minutes to enjoy faster 4G internet when your other modems are too slow.

no.php – Transparent reverse proxy written in PHP that allows you to not have to write PHP any more

This little project will probably be my only contribution to the world of PHP.

The code is at https://github.com/michaelfranzl/no.php

This short, single-file, 80-line PHP script is a simple and fully transparent HTTP(S) reverse proxy written in PHP that allows you to never have to use PHP again for a new project, if you feel so inclined, for example if you are forced to host on a fully 3rd-party-managed server where you can’t do more than run PHP and upload files via FTP. The PHP script simply reads all requests from a browser pointed to it, forwards them (via PHP’s curl library) to a web application listening at another URL (e.g. on a more powerful, more secure, more private, or more capable server in a different data center), and returns the responses transparently and unmodified.

Supports:

  • Regular and XMLHttpRequests (AJAX)
  • All HTTP headers without discrimination
  • GET and POST verbs
  • Content types (HTTP payload) without discrimination
  • Redirects (internal redirects are rewritten to relative URIs)

Does not support (or not tested):

  • HTTP verbs other than GET and POST (but these are usually emulated anyway)
  • HTTP greater than version 1.1 (e.g. reusable connections)
  • Upgrade to websocket (persistent connections)
  • Multipart content type

Usage illustrated by the standard example

You have a non-PHP web application (called the “backend”) listening on https://myapp.backend.com:3000 but due to constraints you must make it available on a shared hosting server called https://example.com/subdir which only supports PHP and can’t be configured at all. On latter server, Apache (or Nginx, doesn’t matter) will usually do the following:

  1. If a URI points to a .php file, this file will be interpreted
  2. If a URI points to a file that is not existing, a 404 status will be returned.

Using no.php, to accomodate the second case, all URIs of the proxied web app (including static files) must be appended to the URI https://example.com/subdir/no.php. For example:

If your backend app supports that extra /subdir/no.php prefix to all paths, you are all set and ready to use no.php. Then:

  1. Simply copy no.php into the subdir directory of example.com
  2. Change $backend_url in no.php to "https://myapp.backend.com:3000"
  3. Point a browser to https://example.com/subdir/no.php

Project status

Experimental. Use only if you know what you are doing.

100% HTTPS in the internet? Non-Profit makes it possible!

Selection_008HTTPS on 100% of websites in the internet? This just has gotten a lot easier! Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. Let’s Encrypt is a service provided by the Internet Security Research Group (ISRG), a Section 501(c)(3) Non-Profit entity dedicated to reduce financial, technological, and education barriers to secure communication over the Internet.

Let’s Encrypt offers free-of-cost certificates that can be used for HTTPS websites, even when these websites are ran for commercial purposes. Unlike traditional CA’s they don’t require cumbersome registration, paperwork, set-up and payment. The certificates are fetched in an automated way through an API (the ACME Protocol — Automatic Certificate Management Environment), which includes steps to prove that you have control over a domain.

Dedicated to transparency, generated certificates are registered and submitted to Certificate Transparency logs. Here is the generous legal Subscriber Agreement.

Automated API? This sounds too complicated! It is actually not. There are a number of API libraries and clients available that do the work for you. One of them is Certbot. It is a regular command-line program written in Python and the source code is available on Github.

After downloading the certbot-auto script (see their documentation), fetching certificates consists of just one command line (in this example certs for 3 domains are fetched in one command with the -d switch):

With the -w  flag you tell the script where to put temporary static files (a sub-folder .well-known  will be created) that, during the API control flow, serve as proof to the CA’s server that you have control over the domain. This is identical to Google’s method of verifying a domain for Google Analytics or Google Webmaster Tools by hosting a static text file.

Eventually, the (already chained, which is nice!) certificate and private key are copied into /etc/letsencrypt/live/example.com/ :

Then it is only a matter of pointing your web server (Nginx, Apache, etc.) to these two files, and that’s trivial.

Let’s Encrypt certificates are valid for 90 days. The automatic renewal of ALL certificates that you have loaded to your machine is as easy as …

… which they suggest should be put into a Cron job, run twice daily. It will renew the certificates just in time. No longer do you have to set a reminder in your calendar to renew a certificate, and then copy-paste it manually!

A bit of a downside is that Let’s Encrypt unfortunately doesn’t support wildcard domain certificates. For these, you still have to pay money to some other CA’s who support them. But in above shown code example, you would generate only 1 certificate for the domains example.com and its two subdomains www.example.com and blah.example.com. The two subdomains are listed in the Subject Alternative Name field of the certificate, which is as close to wildcard subdomains as it gets. But except for SAAS providers and other specialized businesses, not having wildcard certificates should not be too big of an issue, especially when one can automate the certificate setup.

On the upside, they even made sure that their certificates work down to Windows XP!

Today, I set up 3 sites with Let’s Encrypt (one of them had several subdomains), and it was a matter of a few minutes. It literally took me longer to configure proper redirects in Nginx (no fault of Nginx, I just keep forgetting how it’s done properly) than to fetch all the certificates. And it even gave me time to write this blog post!

Honestly, I never agreed with the fact that for commercial certificate authorities, one has to pay 1000, 100 or even 30 bucks per certificate per year. Where’s the work invested into such a certificate that is worth so much? The generation of a certificate is automated, and is done in a fraction of a second on the CPU. Anyway, that now seems to be a thing of the past.

A big Thumbs-up and Thanks go to the Let’s Encrypt CA, the ISRG, and to Non-Profit enterprises in general! I believe that Non-Profits are the Magic Way of the Future!

Icon made by Freepik from www.flaticon.com 

Teamviewer alternative: How to get a Remote Desktop VNC connection via SSH over an intermediate server, avoiding firewalls

What to do when Teamviewer suddenly doesn’t connect or you can’t or don’t want to use it for other reasons? What if a friend needs urgent assistance and you need to see his screen to help out? Standard Open Source tools to the rescue! If you know how to use SSH from the command line and have access to an user account on a remote server running SSHD, then this article will save you!

Teamviewer-like products are so popular because they solve a real problem: To connect from one household computer to another is not straightforward because we all use regular modems/routers to connect to the internet. They are usually not set up for Port Forwarding. In laymans terms this means: You can initiate a connection to  the internet, but the internet never can initiate a connection to you. This quandary has only one solution: an intermediary is needed. Teamviewer-like products all offer such intermediary servers. Data is never directly sent from one computer to the other. Data is passed through a server (which allows for all kinds of spying by the way, if the encryption is not good enough!)

There are tons of (unfortunately for me) half-working instructions in the web about how the commands must look like. I took me several hours to wrap my mind around the problem. For this article, I’ve decided to make an image gallery so that you can see easier what is going on behind the scenes. Running just 4 commands will do the trick!

The following list and image shows the starting point of our situation:

  • We are sitting in front of the computer called “sittinghere”.
  • We want to see the screen of the computer called “overthere”.
  • There is a server called “hopper” which runs an ssh daemon (sshd) listening on the standard port 22. Our data will ‘hop’ though there, hence the name “hopper”.

 

The initial battlefield: Regular firewalls are installed for "sittinghere" and "overthere". "hopper" has a firewall with only port 22 open.
The initial situation: Regular firewalls are constrict “sittinghere” and “overthere”. “hopper” has a firewall with only port 22 open.

We instruct our friend, sitting in front of the computer “overthere”, to start any kind of VNC server. There are many products for Windows, Mac OS, and Linux available. I’m using Linux and decided for x11vnc because it allows access to the screen of the currently logged in user instead of starting a new user session. The command is:

After this command, our situation has changed. See the following image. The VNC server has started listening on port 5900 (see lower right corner):

 

A VNC server is started "overthere". It listens on port 5900.
A VNC server is started “overthere”. It listens on port 5900.

Now we have to instruct our friend, sitting on “overthere”, to run a ssh command to connect to “hopper”. You can make a little batch script for this to make it more convenient, but this is not the focus of this article. The command is:

With this command, sshd on “hopper” is instructed to create a socket on port 7001. And when someone connects to this port, it will be as if the same connection had been made on “overthere” port 5900. In the code above, “localhost” refers to the computer “overthere” because the command is executed on this computer.

Let’s see how our situation now looks like:

 

An ssh client is started "overthere" with Remote Port Forwarding options. A connection is made to sshd, running on "hopper". sshd opens a port localhost:7001 and listens for incoming connections from localhost.
An ssh client is started “overthere” with Remote Port Forwarding options. A connection is made to sshd, running on “hopper”. sshd opens a port on localhost:7001 and listens for incoming connections.

Now that “overthere” has done its connection to “hopper”,  it is time for “sittinghere” to connect to “hopper” too. Here is the command:

This means: A socket on port 7002 will be created on localhost (“sittinghere”). If someone connects to this port, it will be as if the same connection had been made on port 7001 on “hopper”. Here’s the new situation:

 

"sittinghere" starts ssh with Local Port Forwarding options. It connects to sshd running on port 22 of "hopper". It also creates port 7002 on localhost and listens for incoming connections.
“sittinghere” starts ssh with Local Port Forwarding options. It connects to sshd running on port 22 of “hopper”. It also creates port 7002 on localhost and listens for incoming connections.

Now, remember that a connection to port 7001 on “hopper” will have the same effect as if the same connection had been made on “overthere”. This means we will have a kind of ripple-through effect: As soon as we connect to port 7002 on “sittinghere”, the connection will ripple through until it connects to port 5900 of “overthere”. And this endpoint is our VNC server.

Now let’s connect with a VNC client from “sittinghere” to “overthere”. You will find lots of good VNC clients in the internet. Just connect to

which is equivalent to

This will start our connection cascade, and the final situation looks like this:

 

On "sittinghere", a VNC viewer is started and told to connect to localhost port 7002. This connection is detected by ssh which makes sshd running on "hopper" connect to port 7001, which causes ssh running on "overthere" connect to port 5900. Now the route is complete and we can see the remote screen!
On “sittinghere”, a VNC viewer is started and told to connect to localhost port 7002. This connection is detected by ssh which makes sshd running on “hopper” connect to port 7001, which causes ssh running on “overthere” to connect to port 5900. Now the route is complete and we can see the remote screen!

 

Congratulations, we’re now all connected through! If you have set a password (we’ve set it to “PASSWORD” in the above example), you now will see the remote screen. Note that we didn’t even have to execute a command on “hopper”, nor even reconfigure any firewall! My experience is that the quality and speed of the transmitted remote image is much better with this method than with commercial products. Of course, this is because commercial products have to divide and share bandwidth across all users.

The SSH connections will stay alive until you terminate them. So, just type “exit” in the ssh terminals opened at “sittinghere” and “overthere” that we have been opened previously (to “hopper”).

I’m glad I don’t have to rely on commercial products only any more!

Debian Linux HowTo: Bridging WLAN to Ethernet for Access Point (Infrastructure Mode) for Android Phones

wlan card

I am using the Wireless (WLAN) mainly to connect my mobile phone to the internet, for faster downloads and to test mobile apps. First, I only used Apple devices (such as iPad, iPod, iPhone, etc.), and those could connect without problems to a so-called Ad-Hoc network. However, many mobile devices, such as Android, unfortunately will NOT connect to an Ad-Hoc network, for reasons which are very well explained on this How-To Geek posting (it taught me about many things I didn’t know!).Since I’ve recently given up on Apple products and only use Android phones, I needed a definite answer to this problem. And I found it today.

As you may know, there are basically 2 modes to operate a wireless network: “Ad-Hoc” and “Infrastructure” (the latter one also called “Access Point” or shorter “AP”) mode. Cheaper Wireless cards only support the Ad-Hoc mode, but do NOT support the AP mode.

So, I thought: Let’s just buy a WLAN card which supports the AP mode. I bought the Intel Centrino Advanced-N 6235 (Link to official Intel product page). I found it here on Amazon: Intel Network 6235AN.HMWWB Centrino WiFi Card Half Mini PCI Express Advanced-N 6235 Dual Band Bluetooth

It is supported beginning with Kernel version 3.2. I mounted it, and was planning to use the Network Manager of Debian Wheezy / Gnome 3 to quickly set up an AP Hotspot. Easier said than done! Because even though there is an option to set “Infrastructure” mode, my Android phone still would not connect. It would simply write “Ad-Hoc Connecting” and stop there, even though I had set the Infrastructure mode.

 

Network Manager in Debian Wheezy / Gnome3
Network Manager in Debian Wheezy / Gnome3

 

Network Manager in Debian Wheezy / Gnome3 offering "Infrastructure" mode which is not recognized by an Android smartphone, even though the network card supports AP and is fully supported by the Kernel.
Network Manager in Debian Wheezy / Gnome3 offering “Infrastructure” mode which is not recognized by an Android smartphone, even though the network card supports AP and is fully supported by the Kernel.

 

I had to wade through a LOT of web postings, all suggesting not-really-working ‘solutions’ until I found a synthesis of all the collected information that worked for me.

It turns out that you need a dedicated user-space program for ‘driving’ the AP hardware contained in your network chip, and this is hostapd . It seems, you can’t do without.

I found this blog which offered a bash script to automate the job, but it only worked for Ubuntu, and not for Debian due to different configuration files. I also found this little Qt program that made the wireless connection work for my phone, but disconnected my laptop from all networks.(It could have been my fault due to misunderstandings though…)

This blog did a good job in explaining what  hostapd  is and gives basic installation and configuration instructions. You should read the post in any event. However, the suggested final solution did not work for me. Yes, the phone would see the generated wireless network, would connect, but immediately disconnect. I have not found the reason for the failure, but it probably lies hidden in the complexity of the set-up which painstakingly involves

  • a locally run DHCP and DNS server,
  • configuration of same,
  • and manual calls to  iptables  (masquerading, forwarding, etc.) to route between eth0 and wlan0 devices

The author of this blog wrote a second post to avoid the locally run DHCP server in favor of re-using the DHCP server of the network (e.g. the modem) by using  dnsmasq , which is yet another locally run server, only a bit simpler, but has to be configured also. I tried it to no avail. Same problem: phone would disconnect immediately. Frustrated, I moved on.

Then I found ths blog which brought a new idea: the concept of bridging between network interfaces instead of using iptables, which, and this is the good news, is supported ‘natively’ by  hostapd and the Linux networking system configured by  /etc/network/interfaces . However, this solution still did not work for me. After modifying  /etc/network/interfaces accordingly, I managed to mess my internet connection up. It turned out that setting up a bridge between Ethernet and Wireless is not that trivial! Even the highly official Debian Wiki BridgeNetworkConnections would not give working results for my case. So, I started crossreferencing between other solutions and finally came up with the following sequence of commands that work for me on my pretty standard Debian Wheezy laptop with one ethernet adapter (eth0) and the above mentioned Intel network adapter (wlan1). You only need to install 2 packages (bridge-utils and hostapd). With my method, there is no need for a locally installed DHCP or DNS server, and no need to modify the /etc/network/interfaces  file. There is no requirement to permanently make changes to your network configuration. In an emergency (if you are stuck somehow), a reboot will reset your network configuration to the defaults. Devices connected to your newly created wireless network will be served by the DHCP and DNS server specified in your router/modem. Your mobile phone will be a regular and equal member of your LAN.

You can turn the following listed commands easily into a Bash script with ‘start’ and ‘stop’ arguments. But I’ll leave that up to you. It’s easy enough once you copy/past the following commands into a terminal window. So, without further ado, as superuser…

… install bridge-utils. These are helper programs.

Next, remove the attached IP address from the Ethernet card eth0. Bridging will not work when an IP address is set.

Next, turn on IPv4 networking for your wireless card. This is necessary, otherwhise one of the next steps will give the error “can’t add wlan1 to bridge br0: Operation not supported”.

Next, create the actual bridge br0 with the helper program brctl:

Next, bridge between ethernet and wireless. The order of the last two arguments is not important:

Next, bring the newly created bridge up, as a virtual device:

At this point, you will have lost your connection to your LAN/WAN. You have to set an IP address, netmask, router, etc. for the bridge. We do this via DHCP:

Now you should be able to access the internet again. Test it! If it doesn’t work, just reboot your computer. We have not made permanent changes to your system (another advantage of this method!)

So far so good. Now we have to create our actual wireless network in AP mode and use our Android phone to test it. Install hostapd:

Create a configuration file somewhere on your drive. I chose the location  /etc/hostapd/my-wlan.conf . Make sure you have the right driver set for your card (see above mentioned blog for more info. n180211 should work in most cases):

(comments are thanks to above mentioned blog)

Now, simply start hostapd with this configuration file as the only argument:

You will see debug messages helping you to see what is going on behind the scenes. Now use your Android phone, enable WIFI, wait for the network “networkname” to appear, connect to it, enter the password “12345678”, open up a browser and see if it works. Make sure that Wireless is turned on in your Network Manager:

gnome network manager wlan

Otherwise you will get the following messages:

To turn off wireless (you really don’t want to be grilled by microwaves 24 hours a day!), you cannot just turn Wireless off in your Network Manager since it seems to ‘damage’ the bridge (I have yet to confirm this a second time), and you won’t be able to access your network/internet. You have to ‘deconstruct’ the bridge in the following way:

Only after that, you can turn of Wireless in your Network Manager. Again, if you are stuck, just reboot.

I hope this helps somebody, it worked for me, if not, write me a comment.

 

File permissions for successful SSH login via authorized_keys

Setting correct file permissions for ssh is a bit tricky

If you want to ssh into your server without being repeatedly prompted for the password you can copy your public ssh key into a file called authorized_keys  in the .ssh subdirectory of the home directory of the remove server account. However, this works only if the permissions for this file are set correctly.

First, if you have not done so already, generate the public key for your local user:

 

This will create a file ~/.ssh/id_rsa.pub

Append the only line in this file into the file ~/.ssh/authorized_keys  of the remote user account. Create the directory and file if it does not exist.

Now try to ssh into your remote account. If ssh is still asking for the remote user’s password, check the permissions of the following files and directories:

  • The permissions of the home directory of the remote user must be 755
  • The permissions of the remote .ssh directory must be 700
  • The permissions of the remote authorized_keys file must be 600

… of course all of those must be owned by the remote user, and not by root.

Now, you should be able to ssh into the remote account without being asked for the password!