Roland Mas: GForge/FusionForge update

gettext
API, I'd like to take the
opportunity to issue a call for translations, knowing that potential
translators won't be too disturbed by unusual tools and formats.
You can grab the current state of the translations from the GForge
repository
browser.
Or, for more long-term involvement, checkout the code through
Subversion or through Bzr (my
gateway branch is available from
bzr.debian.org.
Current statistics are as follows:
fail2ban
, a script that monitors the failed
connections, and sets up firewall rules (for instance) blocking
further connections from the attacking IP addresses. It's good, but
it fills your logs with messages about IPs getting banned and unbanned
after a while. And you're still at risk that the multiple connections
crash the SSH daemon, or trigger a bug in it, or whatever.
A second layer of protection can be to block all SSH connection
attempts except when they come from known IP addresses, but that
doesn't work when you're away from home, and you're locked out. Been
there, done that.
So, some wise people have devised a trick called "port-knocking".
It's similar to only opening the door to people who use a special
knock (think "That's all, folks"): the firewall stays closed, but it
opens a tiny targeted hole to some IP addresses for a limited length
of time, based on a secret handshake. The window for attack is
therefore very small, and the SSH daemon stays idle most of the time.
And you can still log on your hosted server when you're attending
conferences. There are a variety of implementations for this concept.
Some could be web-based (you need to submit the right password to a
web page), some could use other services or a dedicated daemon.
But when I started investigating port-knocking, I wanted something
simple, preferably with no dependencies on a daemon that would need to
be exposed to the net and potentially crash. I found an
article on the
Debian Administration
website, but I wasn't entirely satisfied with it. The principles
appealed to me (netfilter-only, secret handshake in the form of
opening connections to secret ports), though, so I evolved it into my
own implementation, which I proudly present to you today.
The goals of this implementation were:
dc
to be installed, for big-integer arithmetic):
Okay. So this function calculates ports, now what? Now we're going to define a few chains by which netfilter will store states of IP addresses as they progress through the handshake:calc_knock_ports () secret=$1 bottomport=$2 topport=$3 nbports=$(( $topport - $bottomport + 1 )) hash=$(TZ=UTC date +%Y-%m-%d-%H-$secret md5sum awk ' print $1 ' tr a-z A-Z) num=$(echo 16i $hash f dc) pk_port1=$(echo $num $nbports 0 ^ / $nbports % $bottomport + f dc) pk_port2=$(echo $num $nbports 1 ^ / $nbports % $bottomport + f dc) pk_port3=$(echo $num $nbports 2 ^ / $nbports % $bottomport + f dc) pk_port4=$(echo $num $nbports 3 ^ / $nbports % $bottomport + f dc) pk_port5=$(echo $num $nbports 4 ^ / $nbports % $bottomport + f dc)
These chains use thesetup_portknocking_tables () iptables -N portknock_into_phase1 iptables -A portknock_into_phase1 -m recent --name PK_PHASE1 --set # iptables -A portknock_into_phase1 -j LOG --log-level notice --log-prefix "INTO PK_PHASE1: " iptables -N portknock_into_phase2 iptables -A portknock_into_phase2 -m recent --name PK_PHASE1 --remove iptables -A portknock_into_phase2 -m recent --name PK_PHASE2 --set # iptables -A portknock_into_phase2 -j LOG --log-level notice --log-prefix "INTO PK_PHASE2: " iptables -N portknock_into_phase3 iptables -A portknock_into_phase3 -m recent --name PK_PHASE2 --remove iptables -A portknock_into_phase3 -m recent --name PK_PHASE3 --set # iptables -A portknock_into_phase3 -j LOG --log-level notice --log-prefix "INTO PK_PHASE3: " iptables -N portknock_into_phase4 iptables -A portknock_into_phase4 -m recent --name PK_PHASE3 --remove iptables -A portknock_into_phase4 -m recent --name PK_PHASE4 --set # iptables -A portknock_into_phase4 -j LOG --log-level notice --log-prefix "INTO PK_PHASE4: " iptables -N portknock_into_phase5 iptables -A portknock_into_phase5 -m recent --name PK_PHASE4 --remove iptables -A portknock_into_phase5 -m recent --name PK_PHASE5 --set iptables -A portknock_into_phase5 -m recent --name PK_ESTABLISHED --set # iptables -A portknock_into_phase5 -j LOG --log-level notice --log-prefix "INTO PK_PHASE5: " iptables -N portknock_accept iptables -A portknock_accept -m limit -j LOG --log-level notice --log-prefix "ACCEPTED AFTER PORTKNOCKING: " # iptables -A portknock_accept -m recent --name PK_PHASE5 --remove iptables -A portknock_accept -j ACCEPT iptables -N portknocking
recent
module, which seems to be commonly
available in standard kernels. You'll notice how, as one packet goes
through these rules, its originating IP address moves from one set of
"recent" addresses to the next. But no logic exists yet to make the
packet actually go through these rules, so here comes the glue:
Right. This function adds rules to therefresh_portknocking () calc_knock_ports f00b4r 10000 10999 iptables -F portknocking iptables -A portknocking -p tcp --dport $pk_port1 -m state --state NEW -j portknock_into_phase1 iptables -A portknocking -p tcp --dport $pk_port2 -m state --state NEW -m recent --rcheck --name PK_PHASE1 --seconds 5 -j portknock_into_phase2 iptables -A portknocking -p tcp --dport $pk_port3 -m state --state NEW -m recent --rcheck --name PK_PHASE2 --seconds 5 -j portknock_into_phase3 iptables -A portknocking -p tcp --dport $pk_port4 -m state --state NEW -m recent --rcheck --name PK_PHASE3 --seconds 5 -j portknock_into_phase4 iptables -A portknocking -p tcp --dport $pk_port5 -m state --state NEW -m recent --rcheck --name PK_PHASE4 --seconds 5 -j portknock_into_phase5 # echo clear > /proc/net/ipt_recent/PK_DONE echo clear > /proc/net/ipt_recent/PK_PHASE1 echo clear > /proc/net/ipt_recent/PK_PHASE2 echo clear > /proc/net/ipt_recent/PK_PHASE3 echo clear > /proc/net/ipt_recent/PK_PHASE4 echo clear > /proc/net/ipt_recent/PK_PHASE5
portknocking
chain. A
packet injected into this ruleset will, depending on its destination
port and whether its source IP address has already been seen, end up
in one of the PK_PHASE* sets. All we have to do now is therefore to
send some packets to this portknocking
chain, and use the
port-knocking sets to decide whether to accept incoming connections or
not:
This example only mentions accepting incoming SSH connections, but it's in no way a limitation: a server of mine uses similar rules to DNAT certain ports to internal IP addresses. And there we have it for the server part: incoming SSH connections are usually ignored (well, handled by the rest of the firewall script, but let's assume that it drops these packets by default), but if one IP address knows the appropriate ports and sends a connection attempt to them in order, then it'll be able to open SSH connections for a little while after that. Of course, it's going to be boring if one has to send these packets by hand, but it can be easily automated by a script. Here's aiptables -A INPUT -j portknocking iptables -A INPUT -m recent --rcheck --seconds 5 --name PK_PHASE5 -m state --state NEW -p tcp --dport ssh -j portknock_accept
~/bin/portknock.sh
I have:
It's designed to be called with two parameters, a host and a port, and it needs#! /bin/sh host=$1 port=$2 calc_knock_ports () [...] calc_knock_ports f00b4r 10000 10999 for i in $pk_port1 $pk_port2 $pk_port3 $pk_port4 $pk_port5 ; do nc -w 1 $host $i < /dev/null > /dev/null 2>&1 done nc $host $port
netcat
in addition to dc
. Why the last line, I hear you
cry? Because then I can just add the following lines to my
~/.ssh/config
:
...and SSH will automagically tunnel its network socket through the script, which will in turn happily tunnel that throughHost blahblah IdentityFile foobar ProxyCommand /home/roland/bin/portknock.sh %h %p
netcat
after
completing the secret handshake.
And when I type ssh myserver
on my laptop, interesting stuff happens
behind the scenes, and a special, just-for-me hole is opened in the
server firewall, just for the few seconds I need to establish the SSH
session (packets belonging to established TCP sockets are allowed by
the firewall's connection tracking).
Note: This article is deliberately short on details and
ready-to-run scripts. Firstly because firewall scripts vary wildly so
any script would have to be adapted anyway, but mostly because
security is best handled with one's brain switched on. Fiddling with
a firewall can easily open gaping holes or lock everyone out. So
please make sure you understand what goes on before blindly pasting
stuff into your own setup. Some of the lines that are commented out
may also be of interest, and were left as an exercise for the reader.
Other lines were not included, and are also left as a rather important
exercise to the reader; note in particular how the netfilter rules as
currently established do not mitigate the replay attacks...
gforge-plugin-mediawiki
binary package (it'll have to go through
NEW, but that seems to be rather fast these days). Testing and
reporting and bugfixing are most welcome, of course.
I also went through a round of cleanups in the packaging. No more
Lintian overrides, far fewer Lintian errors and warnings, and some
fixes for PostgreSQL 8.3 compatibility.
ucf
. So there.aptitude install
gforge-web-apache2
, and the only interactions it'll require are to
type the admin password (twice) and to accept (or integrate by hand)
a change in the PostgreSQL config file.ucf
for management of config files.dbconfig-common
,
too. But since I'm not sure it's going to be good enough, that's
not very high on my priority list.gforge.pot
contains about 2200 strings. But even
reading and fixing (or removing) the obviously incorrect
translations would help.Sometimes I think this should be renamed Planet Buxy.$ planet-scores.sh Planet Debian-FR : 19 Rapha l Hertzog 4 Roland Mas 3 Jean-Christophe Dubacq 2 Gr gory Colpart 2 Alexis Sukrieh
Newly added contributors to that planet have all their recent articles aggregated, not only the ones they wrote since they were added.Planet Debian-FR (utilisateurs) : 10 Julien Candelier 8 Emilien Macchi 4 Guilhem Bonnefille 3 Shams Fantar 1 Rapha l Hertzog 1 Olivier Berger (perso) 1 Jean-Christophe Dubacq 1 Jean-Baptiste H tier (djib) 1 Eric Veiras Galisson
Planet "Christian loves rugby".Planet Debian : 40 Christian Perrier 2 Russell Coker 2 Raphael Geissert 1 Wouter Verhelst 1 Steve Kemp 1 Romain Francoise 1 NOKUBI Takatsugu 1 Michal iha 1 John Goerzen 1 Joey Schulze 1 Gerfried Fuchs 1 Fathi Boudra 1 Enrico Zini 1 Emanuele Rocca 1 Dirk Eddelbuettel 1 David Welton 1 Christine Spang 1 Antti-Juhani Kaijanaho 1 Adam Rosi-Kessel
I know I have an encoding problem on some planets, but that script is a very basic curl+shell+sed+grep+recode+sort+uniq pipeline, and I only use it for the amusement value. Maybe I'll recode it with a proper RSS parser some day if I feel utterly bored.debian-community.org : 4 Holger Levsen 3 Andrew Donnellan 2 Evgeni Golov 1 Wolfgang Lonien 1 Rapha l Hertzog 1 Martin Albisetti 1 Marcos Marado 1 Jean-Christophe Dubacq 1 Cord Beermann 1 Benjamin A'Lee 1 Andreas Putzo $
geek-fr
and geek-en
tags I had, and replace them with the generic
geek
tag. I also created fr
and en
tags, one of which should be
present on all articles. To preserve the existing RSS feeds,
geek-fr
and geek-en
have been redefined as simply the intersection
of geek
and fr
or en
, thanks to Ikiwiki. I could also create a
photo-fr
feed and so on, but so far I don't think it's warranted.
Next.