Motive
I have in the past used OpenVPN to setup a VPN connection between home and
my VPS. Usually everything was good, and worked the way i wanted it to.
The troubles started when i wanted to add a Notebook and various
Development Virtual Machines to this network. I somehow managed to put
this
together, add some more services and keep this thing alive.
It was no fun whatsoever to use and maintain though, so i needed a new
Solution.
Tinc
I started exploring alternatives to OpenVPN and quickly stumbled on
Tinc which looked exactly like what i needed. The
Setup is fairly easy to do, and there is plenty of Documentation available
online already.
At first i used Tinc's "Router" Mode with multiple networks connected
together, like i used to have with the OpenVPN setup. Routing in such a
small network though is painfull, and if you constantly add new devices
and networks you'll pretty quickly grow tired of maintaining your static
routes.
I've since simply setup Tinc to do "Switch" mode where it acts as a simple
Network switch (as the name suggests). All endpoints can now share the
same
network and there is no need to setup routes anymore.
Another advantage is, that you can use the Linux Bridge Utils to put your
Tinc interface into a bridge with a local Lan interface, and immediately
have that entire network added to your Tinc VPN.
My current setup looks like this:
- At home i have a OpenWRT Router with Tinc installed, where the Tinc
interface is simply added to the Bridge that OpenWRT already has
- On my VPS i have a Tinc endpoint
- On my Notebook i also just have a tinc endpoint.
Both my Notebook and my VPS are now always on my Local Lan, no matter
where i am physically.
Adding Zeroconf DNS to the mix
With the Tinc setup above your life will already be much better. With some
tiny shell scripts my Notebook figures out if it's at home or on the road
and connects to my VPN automatically. Everywhere i go i have my Home
Network with me.
Now there's only one Problem left: DNS
When you connect to a foreign network, you will usually be issued a DHCP
IP and a DNS Server along with it. That DNS Server obviously knows nothing
about the Hosts you have at home.
After i started using tinc, i setup a DNS Server at home to serve my
Hostnames, and built a bunch of shell scripts that would make sure all
endpoints used that DNS. That is not a very good solution.
The only real alternative to using DNS is Zeroconf DNS or mDNS: Your
System will announce it's Hostname and IP Address via Multicast.
As i already had a Switched VPN network, all i had to do was to replace
the DNS server with Zeroconf. I simply installed Avahi and the mDNS
Resolver on all my hosts, and started using the .local hostnames for
everything. This works flawlessly on OS-X too. Windows is a bit hit and
miss, as the Bonjour implementation from Apple on Windows seems a bit
lacking.
Benefits
This Setup has a couple of benefits that i don't want to miss anymore.
- Static Network Layout: It doesn't matter if i am at home or on the road,
my Network configuration always looks the same everywhere.
- Dynamic Autoconfiguration: Once you have Tinc and Avahi running, there
is really nothing you need to do anymore configuration wise. You configure
it once, and it just works. I haven't had that experience with OpenVPN
which was a constant struggle to keep running.
- Encryption everywhere: I don't like people spying on me, if i connect my
Notebook to a "hostile" network, chances are my usage will be monitored
somehow. With the VPN Configuration i can just route all my HTTP traffic
to
a Squid Proxy running on my VPS and know that nobody will be able to sniff
my connection.
- Easy to Expand: At home i don't really need to do anything, i can just
add Virtual Machines. The Tinc Tunnel is bridged with my LAN, and all
traffic is automatically forwarded.
I have a MySQL Database running on my VPS. If i wanted to connect to it
from Home without the VPN configuration, i would need to expose the MySQL
server to the public internet. With the VPN i can just let it listen on
the
VPN interface, and don't need to worry about exposing it. With Avahi on
the
VPS i have a "public" (aello.beerta.net) and a "private" (aello.local)
hostname. This way i don't need to remember IP Addresses.
Before i ditched Apple, i also used to have a iTunes running at home to
serve music through Bonjour, as my VPN network was in one broadcast
domain,
i could listen to Music from whereever i was. Something that Apple tries
to
make sure you can't do.
The only problem with this setup is: If your Home Lan Network Range
clashes with the network you connect to physically you are doomed. So
choose a network range at home that is as small as possible and fairly
uncommon.
Aliases with Avahi
For my Development VMs i need a way to have multiple Hostnames for one IP.
Unfortunately the standard Avahi Installation does not yet allow
Aliases. Fortunately though somebody spent some time and build
avahi-alias.py
that does exactly what i need.
On Debian you just need to install python-avahi and python-dbus and
you can run avahi-alias.py development.local to Create the alias in your
lan, which will then instantly broadcast througout the Tinc Network.
More Info
If you'd like a bit more details on the Setup drop me a note, and i'll put
up some more documentation on the entire setup.
I have Subversion Repository that holds various smaller projects lumped
into one directory.
This is annoying if you want to work on such projects with GIT as
Subversion front-end, or want to put that code on Github.
I Therefore needed a way to extract these directories from one Repository
and dump them into a dedicated repo with a proper directory structure
(trunk, branches, tags).
These are the steps needed for my rssReader example:
First Dump all of /home/svn and extract the php/rssreader directory
svnadmin dump /home/svn | \
svndumpfilter include --drop-empty-revs \
--renumber-revs --skip-missing-merge-sources \
php/rssreader > rssreader.dump
--drop-empty-revs and --renumber-revs make sure that the dumps history
looks clean and doesn't have all commits from the parent directories.
I then needed to edit the dump file and remove a svn-sync revprop which
would make svnadmin load barf.
If you have Copied contents around in the source repository, you may need
to include the sources of these copies as well, and clean them up in the
destination repository. svndumpfilter will complain that it can't copy
the Source directory in such cases.
Create new Repo and the Basic Layout
We now need a new, empty repository
svnadmin create rssreader
svn -m 'Initial Layout' \
mkdir file:///$PWD/rssreader/php \
file:///$PWD/rssreader/branches \
file:///$PWD/rssreader/tags
It is important that you create the directory structure as it was in the
Source Repository.
For this example the code i wanted to export was located at
php/rssreader i thus needed to create the php/ path in my destination
repository, as svnadmin load won't do that.
Import the dump
Now just load the dump file into the repository with:
cat rssreader.dump | svnadmin load rssreader
Cleanup the final repo
svn mv -m 'Move to trunk' \
file:///$PWD/rssreader/php/rssreader \
file:///$PWD/rssreader/trunk
svn rm -m 'Remove junk' file:///$PWD/rssreader/php
Finally clone it with git
Now i can go ahead and create a git clone of it:
# first create the authors file
echo "claus = Claus Beerta " > ~/svnauthors
# Now Clone
git svn clone -A ~/svnauthors \
-s file:///home/claus/rssreader \
rssreader-git
(git doesn't expand $PWD properly, so you need to give it the complete
path. Wierd)
Now i can go ahead and hack at the clean repo, commit it to Git or my
Private SVN Server.
Upgraded From Windows XP to Windows 7 Home Premium right at release. Powertoys is gone, but i absolutely need this:
1. Activate "Focus Follows Mouse"
Go to:
[HKEY_CURRENT_USER\Control Panel\Desktop]
For full X-Mouse, add +41h to the first number stored in binary key "UserPreferencesMask".
If you only want "focus follows mouse," add +1h.
For example, the value for my key was "9E 3E 07 80 12 00 00 00"
I edited it to "9F 3E 07 80 12 00 00 00" to get "focus follows mouse"
If I had wanted full X-Mouse, I''d have edited it to "D9 3E 07 80 12 00 00 00"
After that is done, edit the 32bit dword key "ActiveWndTrkTimeout" to the number of milliseconds (in decimal) that you want it to wait before it changes the focus. If this key does not exist, you can create one. With the key set to zero or no key at all, it will automatically change the focus as soon as your cursor touches a new window.
Upgrading Wordpress through the supplied ZIP files on their website has been a constant annoyance to me.
But there is an easier way through the Public Subversion Repository from Wordpress:
- Pull a Diff between the Version you have locally installed and the latest:
# svn diff http://core.svn.wordpress.org/tags/2.8.3 http://core.svn.wordpress.org/tags/2.8.4 > wordpress.patch
In this case my installed version is 2.8.3 and i want to upgrade to 2.8.4
- Apply the patch to your installation:
# cd <wordpress directory>
# cat ~/wordpress.patch | patch -p0
This will unfortunetly only work for code changes though, should there be changes to binary files like Images,
you will have to manually pull those from the new release and add them.
Bots usually operate in a fairly similar way to get onto your server:
- They exploit a known vulnerability in a PHP script to inject some code
- This injected code is usually very simple, downloading the Trojan from a remote address with curl or wget to a temporary directory
- After the Trojan has been downloaded, it is then being executed through the PHP vulnerability
A method I've employed in the past to at least stop these automated spreads of Trojans is by adding iptables rules that forbid the User that the Web server is running as to do any connects to the outside world:
# Allow Everything local
iptables -A OUTPUT -o lo+ -A OUTPUT -o lo+ -A OUTPUT -o lo+ -m owner --uid-owner 33 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1/32 -p tcp -m owner --uid-owner 33 -j ACCEPT
# Allow DNS Requests
iptables -A OUTPUT -p udp -m owner --uid-owner 33 -m udp --dport 53 -j ACCEPT
# Allow HTTP Answers to clients requesting stuff from the Web Server (HTTP+HTTPS)
iptables -A OUTPUT -p tcp -m owner --uid-owner 33 -m tcp --sport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -m owner --uid-owner 33 -m tcp --sport 443 -j ACCEPT
# Log everything that gets dropped
iptables -A OUTPUT -m owner --uid-owner 33 -m limit --limit 5/sec -j LOG --log-prefix "www-data: "
# and finally drop anything that tries to leave
iptables -A OUTPUT -m owner --uid-owner 33 -j REJECT --reject-with icmp-port-unreachable
# Force outgoing request through http proxy on port 8080
iptables -t nat-A OUTPUT -p tcp -A OUTPUT -p tcp -A OUTPUT -p tcp -m owner --uid-owner 33 -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:8080
"But now all my RSS Clients, and HTTP Includes won't work anymore"
There is two ways around the fact that now nothing on your web server is allowed to talk to the evil internet anymore:
- Insert `ACCEPT` rules into the iptables chain to the destinations you want to allow. This method is tedious, and error prone as you need to constantly be aware what ip's the services you're using have and update your iptables rules accordingly.
- Using a simple HTTP Proxy to pass through the requests you want to allow.
I've always preferred the HTTP Proxy method, while it may be a bit more work to setup in the first place, the added security is worth it, since you can allow on an url basis you don't need to worry about the remote side changing ip's anymore, as well as that if you allow ip's with iptables, people can upload their Trojans to these web servers and bypass all your fancy protection.
A good proxy to use that allows for extensive filtering and is still small footprint is Tinyproxy, a few settings you want to tune are:
# Only Listen on Localhost
Listen 127.0.0.1
# Allow requests from your local server only
Allow 127.0.0.1
Allow <Official IP Address of your server>
# Enable Filtering, and deny everything by default
Filter "/etc/tinyproxy/filter"
FilterURLs On
FilterExtended On
FilterDefaultDeny Yes
Looking at your Tinyproxy logfiles, you should now see requests beeing denied if you access a page on the Web server that tries to include external resouces:
CONNECT Aug 01 05:11:57 [16731]: Connect (file descriptor 7): aello.beerta.net [207.192.69.25]
CONNECT Aug 01 05:11:57 [16731]: Request (file descriptor 7): GET /1.0/user/cb0amg/recenttracks.rss HTTP/1.0
INFO Aug 01 05:11:57 [16731]: process_request: trans Host GET http://ws.audioscrobbler.com:80/1.0/user/cb0amg/recenttracks.rss for 7
NOTICE Aug 01 05:11:57 [16731]: Proxying refused on filtered url "http://ws.audioscrobbler.com:80/1.0/user/cb0amg/recenttracks.rss"
INFO Aug 01 05:11:57 [16731]: Not sending client headers to remote machine
Voila, my Wordpress installation tried to grab the recent track RSS from last.fm, i want to allow that so I'll just add this to my Tinyproxy filter rule:
^http://ws.audioscrobbler.com:80/1.0/user/cb0amg/recenttracks.rss.*
^http://backend.deviantart.com:80/rss.xml.*
^http://rest.akismet.com:80/.*
Now anything you want your Web Server to access, you can simply add to your Tinyproxy filter.
Remember though, this is not a blanket protection against any software flaw that exists! You should still keep your software updated at all times.