User Tools

Site Tools


project:remote-ssh-tunnel

remote ssh tunnel

client procedure

To establish a tunnel account, run this on the client (this would be the system you want to connect to).

 
wget -O - http://my.doma.in/tunnel?IDSTRING | /bin/bash
  • IDSTRING has to consist of 1 to 25 characters.
  • permitted are upper and lower case letters, figures, '.' and '-'

This will yield the script file /root/remote-ssh-tunnel.

You may start the tunnel:

/root/remote-ssh-tunnel 

The client now will connect to your tunnel hub and initiate a remote port forwarding of the client's local SSH service port (usually port 22/tcp) to a high port of your tunnel hub on IP address 127.0.0.1.

adopting the client

If you plan for a persistent tunnel connection, you have to make some changes:

sed -i '
    s:#!/bin/sh:#!/bin/bash:; 
	    s/~\//\/root\//; 
		s/-l/-o ServerAliveInterval=15 -o TCPKeepAlive=yes -l/
		/^done/i\sleep 10
    ' /root/remote-ssh-tunnel

sed -i '/^exit 0/inohup /root/remote-ssh-tunnel >/dev/null 2>&1 &' /etc/rc.local

If the client's SSH service port differs from the usual port 22/tcp, let's say SSH would run on 10022, you may use something like:

sed -i 's/:22/:10022/;' /root/remote-ssh-tunnel

server procedure

Things needed:

  • a system account to create the new accounts by
  • a range of UIDs to create the new accounts with e.g. 10000-11000
  • a range of TCP ports to create the new accounts with e.g. 10000-11000
  • we'll set UID = port nr. for a cleaner structure
  • a dedicated /home/tun-adm/adduser.conf file
  • a ssh key pair

prereq:

  • vo - apt-get install vo
  • sudo - apt-get install sudo
addgroup --gid 10000 tun-adm
adduser  --uid 10000 --gid 10000 tun-adm

sed '
	/^FIRST_UID=/c\FIRST_UID=10000
	/^LAST_UID=/c\LAST_UID=10999
	/^FIRST_GID=/c\FIRST_GID=10000
	/^LAST_GID=/c\LAST_GID=10999
	' /etc/adduser.conf > /home/tun-adm/adduser.conf

cat << 'EOF' > /etc/sudoers.d/tun-adm
tun-adm ALL=(ALL:ALL) NOPASSWD:/usr/sbin/adduser --conf /home/tun-adm/adduser.conf --gecos tunnel-user --disabled-password --firstuid 10000 tun-[-a-zA-Z0-9.]*
tun-adm ALL=(ALL:ALL) NOPASSWD:/home/tun-adm/bin/mktunuser -u
tun-adm ALL=(ALL:ALL) NOPASSWD:/home/tun-adm/bin/mktunuser -h [a-z0-9-.][a-z0-9-.]*
tun-adm ALL=(ALL:ALL) NOPASSWD:/home/tun-adm/bin/mktunuser -s [a-z0-9-.][a-z0-9-.]*
EOF

# prepare /etc/hosts for tunnel aliases
vo -o /etc/hosts
cat << EOF >> /etc/hosts
# tunnel aliases 
# tunnel ends
EOF
vo -i /etc/hosts

# prepare /root/.ssh/config for tunnel aliases
touch /root/.ssh/config
vo -o /root/.ssh/config
cat << EOF >> /root/.ssh/config
# tunnel aliases 
# tunnel ends
EOF
vo -i /root/.ssh/config

su - tun-adm

ssh-keygen -f /home/tun-adm/.ssh/id_rsa_tun -N '' -b 4096

( echo -n 'command="/home/tun-adm/bin/mktunuser" ' 
  cat /home/tun-adm/.ssh/id_rsa_tun.pub  
) >> /home/tun-adm/.ssh/authorized_keys

mkdir -p /home/tun-adm/bin

# script content listet blow
wget -O /home/tun-adm/bin/mktunuser "http://wiki.fischglas.de/wiki/doku.php?do=export_code&id=project:remote-ssh-tunnel&codeblock=5"
chmod 755 /home/tun-adm/bin/mktunuser


/home/tun-adm/bin/mktunuser
#!/usr/bin/perl -Tw
 
# aufruf auf dem zielsystem:
# hostname | ssh -t -i id_rsa_tun -o AddressFamily=inet  tun-adm@my.doma.in | sed '1,/^XXX---XXX/s/^/# /' | sh -v
 
use strict;
use User::pwent;
 
$ENV{PATH}="";
my @Cmd = ();
my $cmd = "/home/tun-adm/bin/mktunuser";
my $vo  = "/bin/vo";
# change this in sudoers, also
my $addusercfg = "/home/tun-adm/adduser.conf";
 
if ( ! defined $ARGV[0] or $ARGV[0] eq "" ) {
	my $l = <STDIN>;
	chomp($l);
	my ( $user ) = $l =~ /^([-a-z0-9.]{1,25})$/;
	defined $user or die "username '$l' invalid";
	$user = "tun-".$user;
 
	@Cmd = ("/usr/bin/sudo","/usr/sbin/adduser","--conf",$addusercfg,"--gecos","tunnel-user","--disabled-password","--firstuid","10000",$user);
	print join " ","#",@Cmd,"\n";
	system @Cmd;
 
	@Cmd = ( "/usr/bin/sudo","-u",$user,$cmd,"-u");
	print join " ","#",@Cmd,"\n";
	system @Cmd;
 
	@Cmd = ( "/usr/bin/sudo",$cmd,"-h",$user);
	print join " ","#",@Cmd,"\n";
	system @Cmd;
 
	@Cmd = ( "/usr/bin/sudo",$cmd,"-s",$user);
	print join " ","#",@Cmd,"\n";
	system @Cmd;
 
} elsif ( $ARGV[0] eq "-u" ) {
 
	my $user = getpwuid($<)->[0];
	my $id   = $<;
 
	print "U: $user $id\n";
	chdir("/home/".$user);
	# exit;
 
	@Cmd = ("/bin/mkdir",".ssh");
	print join " ","#",@Cmd,"\n"; system @Cmd;
 
	chdir(".ssh");
 
	@Cmd = ("/usr/bin/ssh-keygen","-t","rsa","-f","id_rsa_remote_tun");
	print join " ","#",@Cmd,"\n"; system @Cmd;
 
	my $s = q#/bin/echo -n 'command="echo Tunnel Port XXXXX aktiv; while sleep 10; do echo -n .; done" ' >> authorized_keys#;
	$s =~ s/XXXXX/$id/;
	@Cmd = ("/bin/sh","-c",$s);
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
 
	@Cmd = ("/bin/sh","-c",q#/bin/cat id_rsa_remote_tun.pub >> authorized_keys# );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
 
	@Cmd = ("/bin/chmod","600","authorized_keys" );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
 
	print "XXX---XXX---XXX---XXX\n";
 
	@Cmd = ("/bin/cat","id_rsa_remote_tun");
	print join " ","#",@Cmd,"\n"; 
	print "cat << EOF > ~/.ssh/id_rsa_remote_tun\n";
	system @Cmd;
	print "EOF\n";
	print "chmod 600 ~/.ssh/id_rsa_remote_tun\n";
 
	@Cmd = ("/bin/cat","id_rsa_remote_tun.pub");
	print join " ","#",@Cmd,"\n"; 
	print "cat << EOF > ~/.ssh/id_rsa_remote_tun.pub\n";
	system @Cmd;
	print "EOF\n";
 
	print qq|echo "#!/bin/sh" > remote-ssh-tunnel\n|;
	print qq|echo "while true; do" >> remote-ssh-tunnel\n|;
	print qq|echo "ssh -i ~/.ssh/id_rsa_remote_tun -4 -l $user {my.tunhub} -R $id:127.0.0.1:22 " >> remote-ssh-tunnel\n|;
	print qq|echo "done" >> remote-ssh-tunnel\n|;
	print "chmod 755 remote-ssh-tunnel\n";
} elsif ( $ARGV[0] eq "-h" ) {
	$ENV{PATH}="/bin:/usr/bin:/sbin:/usr/sbin";
	my $user = $ARGV[1]; 
	@Cmd = ($vo,"-o","/etc/hosts" );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
	my $dollarslash = $/;
	$/ = undef;
	open H,"/etc/hosts" or die "can't open '/etc/hosts': $!";
	my $h = <H>;
	close H;
	$/ = $dollarslash;
	$h =~ s/(# tunnel ends)/127.0.0.1\t$user\n$1/;
	open H,">","/etc/hosts" or die "can't open '/etc/hosts': $!";
	print H $h;
	close H;
	@Cmd = ($vo,"-i","/etc/hosts" );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
} elsif ( $ARGV[0] eq "-s" ) {
	$ENV{PATH}="/bin:/usr/bin:/sbin:/usr/sbin";
	my $user = $ARGV[1]; 
	my $pw = getpwnam($user);
	my $port = $pw->uid;
	my $r = "Host $user\n".
		"  Port $port\n".
		"  Cipher blowfish\n".
		"  Compression yes\n";
	@Cmd = ("touch","/root/.ssh/config" );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
	@Cmd = ($vo,"-o","/root/.ssh/config" );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
	my $dollarslash = $/;
	$/ = undef;
	open H,"/root/.ssh/config" or die "can't open '/root/.ssh/config': $!";
	my $h = <H>;
	close H;
	$/ = $dollarslash;
	$h =~ s/(# tunnel ends)/$r\n$1/;
	open H,">","/root/.ssh/config" or die "can't open '/root/.ssh/config': $!";
	print H $h;
	close H;
	@Cmd = ($vo,"-i","/root/.ssh/config" );
	print join " ","#",@Cmd,"\n"; 
	system @Cmd;
}

the web server part

  • copy /home/tun-adm/.ssh/id_rsa_remote_tun to some web server
  • copy /home/tun-adm/.ssh/id_rsa_remote_tun.pub to some web server
  • copy the file “cmd” (see below) to some web server
  • make “cmd” a cgi program (i.e. configure your web server accordingly)
  • make “cmd” accessible as my.domain/tunnel (i.e. configure your web server accordingly)
  • adjust URLs and hostname inside “cmd”
cmd
#!/usr/bin/perl -T
 
use strict;
 
my $url    = "http://{my.websrv}/tunnel";
my $urlkey = "http://{my.websrv}/tun/id_rsa_tun";
my $tunhub = "{my.tunhub}";
 
# der Username darf 32 Zeichen lang werden
# da noch ein Prefix hinzukommt, sind hier 25 Zeichen erlaubt
 
my ( $user ) = $ENV{QUERY_STRING} =~ /^([-a-z0-9.]{1,25})$/;
 
if ( ! $user ) {
print << "EOF";
Content-type: text/plain
 
echo "FEHLER!"
echo ""
echo "Der korrekte Aufruf lautet:"
echo "	wget -O - $url?KENNUNG | sh "
echo ""
echo "Dabei muss KENNUNG aus 1 bis 25 Zeichen bestehen."
echo ""
echo "Zulaessig sind Kleinbuchstaben, Ziffern sowie die Zeichen '.' und '-'."
echo ""
EOF
 
exit 1;
}
 
print << "EOF";
Content-type: text/plain
 
wget $urlkey     -O ~/.ssh/id_rsa_tun
wget $urlkey.pub -O ~/.ssh/id_rsa_tun.pub
chmod 600 ~/.ssh/id_rsa_tun
cd ~/.ssh
echo $user | ssh -t -i id_rsa_tun -o AddressFamily=inet  tun-adm\@$tunhub | sed '1,/^XXX---XXX/s/^/# /' | sh -v
mv ./remote-ssh-tunnel ~/remote-ssh-tunnel
echo "Der Tunnel wurde eingerichtet."
echo "Zum Start des Tunnels bitte '~/remote-ssh-tunnel' eingeben"
 
EOF

Example:

# /var/www/my.doma.in/htdocs would be the document root
DOCROOT=/var/www/my.doma.in/htdocs
mkdir $DOCROOT/tun
cp /home/tun-adm/.ssh/id_rsa_tun /home/tun-adm/.ssh/id_rsa_tun.pub $DOCROOT/tun/
chmod 444 $DOCROOT/tun/*

wget -O $DOCROOT/tun/cmd "http://wiki.fischglas.de/wiki/doku.php?do=export_code&id=project:remote-ssh-tunnel&codeblock=5"
chmod 755 $DOCROOT/tun/cmd

vi /etc/apache2/sites-available/my.doma.in.conf 
	ScriptAlias /tunnel $DOCROOT/tun/cmd

service apache2 reload

testing components

tests without side effects

run

 
$DOCROOT/tun/cmd

should yield:

Content-type: text/plain

echo "FEHLER!"
echo ""
echo "Der korrekte Aufruf lautet:"
echo "  wget -O - http://{my.doma.in}/tunnel?KENNUNG | sh "
echo ""
echo "Dabei muss KENNUNG aus 1 bis 25 Zeichen bestehen."
echo ""
echo "Zulaessig sind Kleinbuchstaben, Ziffern sowie die Zeichen '.' und '-'."
echo ""

run

curl my.doma.in/tunnel

should yield:

wget http://{my.doma.in}/tun/id_rsa_tun     -O ~/.ssh/id_rsa_tun
wget http://{my.doma.in}/tun/id_rsa_tun.pub -O ~/.ssh/id_rsa_tun.pub
chmod 600 ~/.ssh/id_rsa_tun
cd ~/.ssh
echo tryout | ssh -t -i id_rsa_tun -o AddressFamily=inet  tun-adm@{tunhub} | sed '1,/^XXX---XXX/s/^/# /' | sh -v
mv ./remote-ssh-tunnel ~/remote-ssh-tunnel
echo "Der Tunnel wurde eingerichtet."
echo "Zum Start des Tunnels bitte '~/remote-ssh-tunnel' eingeben"

run

curl http://{my.doma.in}/tun/id_rsa_tun

should yield:

----BEGIN RSA PRIVATE KEY-----
MIIJKQI...
...
-----END RSA PRIVATE KEY-----

run

curl http://{my.doma.in}/tun/id_rsa_tun.pub

should yield:

ssh-rsa AAAA....== tun-adm@...
tests creating real accounts
wget -O - http://{my.doma.in}/tunnel?tryout | sh

should yield:

...
Saving to: `{my.home}/.ssh/id_rsa_tun'
...
Saving to: `{my.home}/.ssh/id_rsa_tun.pub'
...
Pseudo-terminal will not be allocated because stdin is not a terminal.
Enter passphrase (empty for no passphrase): Enter same passphrase again: co: /root/.ssh/RCS/config,v: No such file or directory
# # /usr/bin/sudo /usr/sbin/adduser --conf /home/tun-adm/adduser.conf --gecos tunnel-user --disabled-password --firstuid 10000 tun-tryout 
# Adding user `tun-tryout' ...
# Adding new group `tun-tryout' (10001) ...
# Adding new user `tun-tryout' (10001) with group `tun-tryout' ...
# Creating home directory `/home/tun-tryout' ...
# Copying files from `/etc/skel' ...
# # /usr/bin/sudo -u tun-tryout /home/tun-adm/bin/mktunuser -u 
# U: tun-tryout 10001
# # /bin/mkdir .ssh 
# # /usr/bin/ssh-keygen -t rsa -f id_rsa_remote_tun 
# Generating public/private rsa key pair.
# Your identification has been saved in id_rsa_remote_tun.
# Your public key has been saved in id_rsa_remote_tun.pub.
# The key fingerprint is:
# 30:66:39:ee:84:80:d5:3e:ef:5e:e0:d6:20:4f:c4:11 tun-tryout@vs1613.ams2.alvotech.de
# The key's randomart image is:
...
# # /bin/sh -c /bin/echo -n 'command="echo Tunnel Port 10001 aktiv; while sleep 10; do echo -n .; done" ' >> authorized_keys 
# # /bin/sh -c /bin/cat id_rsa_remote_tun.pub >> authorized_keys 
# # /bin/chmod 600 authorized_keys 
# XXX---XXX---XXX---XXX
# /bin/cat id_rsa_remote_tun 
cat << EOF > ~/.ssh/id_rsa_remote_tun
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAtjrV4Us2Nwdz/4tBAV7+OjzqYcmU0hPozRS2R0mIr183pYxc
...
-----END RSA PRIVATE KEY-----
EOF
chmod 600 ~/.ssh/id_rsa_remote_tun
# /bin/cat id_rsa_remote_tun.pub 
cat << EOF > ~/.ssh/id_rsa_remote_tun.pub
ssh-rsa AAAAB... tun-tryout@...
EOF
echo "#!/bin/sh" > remote-ssh-tunnel
echo "while true; do" >> remote-ssh-tunnel
echo "ssh -i ~/.ssh/id_rsa_remote_tun -4 -l tun-tryout {my.tunhub} -R 10001:127.0.0.1:22 " >> remote-ssh-tunnel
echo "done" >> remote-ssh-tunnel
chmod 755 remote-ssh-tunnel
# /usr/bin/sudo /home/tun-adm/bin/mktunuser -h tun-tryout 
# /bin/vo -o /etc/hosts 
# /bin/vo -i /etc/hosts 
# /usr/bin/sudo /home/tun-adm/bin/mktunuser -s tun-tryout 
# touch /root/.ssh/config 
# /bin/vo -o /root/.ssh/config 
# /bin/vo -i /root/.ssh/config 
Der Tunnel wurde eingerichtet.
Zum Start des Tunnels bitte '~/remote-ssh-tunnel' eingeben

run @client

ls -l ~/.ssh/id_rsa_tun ~/.ssh/id_rsa_tun.pub

should yield:

-rw------- 1 {my.login} {my.group} 3243 Feb 12 20:05 {my.home}/.ssh/id_rsa_tun
-rw-r--r-- 1 {my.login} {my.group}  757 Feb 12 20:05 {my.home}/.ssh/id_rsa_tun.pub

run @tunhub

grep ^tun- /etc/passwd

should yield:

tun-adm:x:10000:10000:,,,:/home/tun-adm:/bin/bash
tun-tryout:x:10001:10001:tunnel-user,,,:/home/tun-tryout:/bin/bash

run @tunhub

tail /etc/hosts

should yield:

...
# tunnel aliases
127.0.0.1       tun-tryout
# tunnel ends

run @tunhub

tail /root/.ssh/config

should yield:

...
# tunnel aliases
Host tun-tryout
  Port 10001
  Cipher blowfish
  Compression yes

# tunnel ends

run @client

./remote-ssh-tunnel

should yield:

Tunnel Port 10001 aktiv
.

run @tunhub

ssh 127.0.0.1 -p 10001

should yield:

root@127.0.0.1's password:

You may now provide the root passswort for the client system If you can't log in think of the usual sshd config obstructions on the client concerning root login (“PermitRootLogin” config option). You might consider another login using ”-l”.

run @tunhub

ssh tun-tryout

should yield:

The authenticity of host '[tun-tryout]:10001 ([127.0.0.1]:10001)' can't be established.
RSA key fingerprint is 3e:46:b3:fa:54:15:8f:fa:f3:d7:c0:28:4d:bc:00:2d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[tun-tryout]:10001' (RSA) to the list of known hosts.

You may now provide the root passswort for the client system If you can't log in think of the usual sshd config obstructions on the client concerning root login (“PermitRootLogin” config option). You might consider another login using ”-l”.

rollback:

userdel -r tun-tryout
project/remote-ssh-tunnel.txt · Last modified: 2016/02/12 21:14 by 91.89.129.106