Avertissement
Description
Environnement
Configuration ftp-proxy
Tests ftp-proxy
Configuration pound
Tests pound


Avertissement

Comme chaque fois que l'on touche aux serveurs proxy, il est nécessaire de prendre des précautions. Je ne garantis donc pas que cette config soit exempte de bugs que, le cas échéant, vous pourrez me transmettre afin que je corrige et mette cette doc à jour.


Description

On dispose d'une machine connectée à internet derrière un routeur/firewall et on ne dispose que d'une ip publique.

le port 80 public du routeur est redirigé vers le port 80 d'un serveur web du réseau local
le port 21 public du routeur est redirigé vers le port 21 d'un serveur ftp du réseau local.

Maintenant imaginons que le serveur soit patché linux-vserver (http://linux-vserver.org) et que sur certains vservers on fasse également tourner des serveurs web et ftp. (Pour la démo on va considérer qu'il y a 2 vservers d'installés).
Il faudra que l'internaute puisse accèder au serveurs web/ftp installés sur le serveur et aux serveurs web/ftp installés sur les vservers.

Il y a plusieurs solutions:

1) Choisir un port différent de 80 sur le routeur et le natter vers l'ip du vserver : cela oblige l'internaute à spécifier le port dans l'url et cela va vite devenir fastidieux lorsqu'il y aura quleques dizaines de vservers (surtout que le routeur ne vas pas natter des dizaines de ports)
2) Utiliser pound pour les redirections web et ftp-proxy pour le ftp.
etc...

Bon disons qu'on va utiliser la 2ème soluce :)


Environnement

Pour que l'on puisse utiliser les noms de domaine, il est préférable d'utiliser un dns local (sinon on se paluche les noms dans les fichiers hosts). De toutes façons c'est une bonne habitude, ne serait-ce que pour faire des tests sur des serveurs de messagerie en cours d'install.

Depuis mon poste de travail je peux joindre les machines par leur nom ou leur ip en utilisant le dns local qui tourne sur une autre debian:
pme@pme-linux:~$ cat /etc/resolv.conf
nameserver 192.168.1.80

pme@pme-linux:~$ host vweb1.domaine.pat
vweb1.domaine.pat has address 192.168.1.241

pme@pme-linux:~$ host srvglus238.net.pat
srvglus238.net.pat has address 192.168.1.241
srvglus238.net.pat mail is handled by 10 mx.net.pat.

On voit bien que les 2 noms de domaine "semblent" être servis par la même machine.

Le serveur s'exécute dans une vmware (ce qui ne change rien à un serveur en dur) et est configuré comme suit:

srvglus238:~# ip addr ls
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:e7:1c:6c brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.241/24 brd 192.168.1.255 scope global eth0
    inet 192.168.1.250/24 brd 192.168.1.255 scope global secondary eth0  => IP vserver vweb5
    inet 192.168.1.242/24 brd 192.168.1.255 scope global secondary eth0  => IP vserver vweb1
    inet6 fe80::20c:29ff:fee7:1c6c/64 scope link
       valid_lft forever preferred_lft forever

srvglus238:~# cat /etc/issue.net
Debian GNU/Linux 5.0

srvglus238:~# uname -a
Linux srvglus238 2.6.29.2-vs2.3.0.36.10-cgroups #2 Tue May 19 15:02:48 CEST 2009 x86_64 GNU/Linux


srvglus238:~# netstat -tpan
Connexions Internet actives (serveurs et établies)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat        PID/Program name
tcp        0      0 192.168.1.241:10024     0.0.0.0:*               LISTEN      1688/amavisd (maste
tcp        0      0 192.168.1.241:3306      0.0.0.0:*               LISTEN      1752/mysqld    
tcp        0      0 192.168.1.241:110       0.0.0.0:*               LISTEN      2125/tcpserver 
tcp        0      0 192.168.1.241:143       0.0.0.0:*               LISTEN      1894/couriertcpd
tcp        0      0 192.168.1.241:783       0.0.0.0:*               LISTEN      1848/spamd.pid 
tcp        0      0 192.168.1.241:8080      0.0.0.0:*               LISTEN      17521/apache2  
tcp        0      0 192.168.1.241:80        0.0.0.0:*               LISTEN      17477/pound    
tcp        0      0 192.168.1.241:21        0.0.0.0:*               LISTEN      17094/ftp-proxy
tcp        0      0 192.168.1.241:2121      0.0.0.0:*               LISTEN      14320/pure-ftpd (SE
tcp        0      0 192.168.1.241:22        0.0.0.0:*               LISTEN      1661/sshd      
tcp        0      0 192.168.1.241:25        0.0.0.0:*               LISTEN      2112/tcpserver 
tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN      17031/slapd    
tcp        0      0 192.168.1.241:22        192.168.1.244:44390     ESTABLISHED 14403/0        
tcp        0      0 192.168.1.241:22        192.168.1.244:54937     ESTABLISHED 3407/2         
tcp        0      0 192.168.1.241:22        192.168.1.244:55843     ESTABLISHED 3392/1         
tcp6       0      0 :::389                  :::*                    LISTEN      17031/slapd  

srvglus238:~# grep ServerName /etc/apache2/sites-enabled/*
/etc/apache2/sites-enabled/mailman:        ServerName mailman.net.pat
/etc/apache2/sites-enabled/srvglus:        ServerName srvglus238.net.pat



Configuration du premier vserver:

srvglus238:~# vserver vweb1 enter

vweb1:/# ip addr ls
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:e7:1c:6c brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.242/24 brd 192.168.1.255 scope global secondary eth0

vweb1:/# netstat -tpan
Connexions Internet actives (serveurs et établies)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat        PID/Program name
tcp        0      0 192.168.1.242:80        0.0.0.0:*               LISTEN      17710/apache2  
tcp        0      0 0.0.0.0:21              0.0.0.0:*               LISTEN      14128/proftpd: (acc

vweb1:/# grep ServerName /etc/apache2/sites-enabled/*
ServerName vweb1.domaine.pat


Configuration du deuxième vserver (il n'y a pas d'apache d'installé, juste un serveur ftp)

vweb5:/# netstat -tpan
Connexions Internet actives (serveurs et établies)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat        PID/Program name
tcp        0      0 0.0.0.0:21              0.0.0.0:*               LISTEN      14179/proftpd: (acc


Il faudra donc :

1) que je puisse taper dans mon navigateur:

http://srvglus238.net.pat => arrivée sur le serveur maître
http://mailman.net.pat => arrivée sur le serveur maître

http://vweb1.domaine.pat => arrivée sur le vserver vweb1

2) que je puisse me connecter en ftp indiféremment sur les répertoires web des données de srvglus238.net.pat, mailman.net.pat, vweb1.domaine.pat.


Configuration ftp-proxy

Sur le serveur web c'est un pure-ftpd qui est installé avec gestion des utilisateurs virtuels. Le serveur apache2 est installé avec php5-cgi et mod_suphp en mode paranoid.

Le fichier de gestion des login, propriètés, mot de passe ressemble donc à ceci:

srvglus238:/etc/pure-ftpd# cat pureftpd.passwd
ftpsrvglus238:$1$8FGRdqn0$gye0aN6z.NMHFTyzAL.aj1:1004:1004:://var/www/srvglus/./::::::::::::
ftpmailman:$1$8FGRdqn0$gye0aN6z.NMHFTyzAL.aj1:1003:1003:://var/www/mailman/./::::::::::::

Sur les 2 vservers j'ai juste installé rapidement un proftpd qui utilise la base des comptes unix (/etc/passwd).

sur le vserver 1 je dispose d'un compte ftpweb1
Sur le vserver 2 je dispose d'un compte ftpweb5

L'install de ftp-proxy est un simple : apt-get install ftp-proxy.

J'ai paramétré le fichier de configuration comme suit:

srvglus238:/etc/proxy-suite# cat ftp-proxy.conf | egrep -v '^#|^$'
[-Global-]
AllowMagicUser    yes
AllowTransProxy    yes
DestinationAddress    invalid.nowhere.zzz
DestinationPort    21
DestinationTransferMode    client
ForceMagicUser    yes
Group            nogroup
Listen        192.168.1.241
LogDestination    daemon
LogLevel        DBG
MaxClients        4
SameAddress        yes
ServerType        standalone
TimeOut        900
User            nobody

On voit que le daemon va écouter sur l'ip 192.168.1.241 port 21.

J'ai donc paramétré pure-ftpd comme ceci (cf netstat -tpan plus haut) pour éviter les conflits:

srvglus238:/etc/pure-ftpd/conf# cat Bind
192.168.1.241,2121

AVANT D'ALLER PLUS LOIN IL EST VITAL DE CONFIGURER UNE REGLE IPTABLES: en effet avec ftp-proxy et au vu de cette config,
le login sera sous la forme :  user@host .

Il serait donc possible de passer par le serveur et de taper au login: login@autreserveur pour se connecter sur une autre machine du web, l'ip source étant la vôtre avec les conséquences que cela pourrait avoir (surtout en ce moment.....)

Je vais donc autoriser le ftp UNIQUEMENT vers des ip appartenant à mon réseau local:

srvglus238:~# iptables -A OUTPUT -p tcp --dport 21 \! -d 192.168.1.0/24 -j DROP

Une peite vérif:
srvglus238:~# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination        
DROP       tcp  --  0.0.0.0/0           !192.168.1.0/24      tcp dpt:21

ATTENTION à adapter si vous possédez déjà d'autres règles.

J'ai tenté avant de passer par iptables de valider une regexp dans le fichier de config mais à priori elle n'est pas reconnue bien que valide:

UserNameRule  ^([[:alnum:]]+)([@])([1][9][2])\.([1][6][8])\.([1])\.([2][4-5]{1}[0-9]{1})$

ou en plus simple: UserNameRule ^([[:alnum:]]+)([@])(192)\.(168)\.(1)\.([2][4-5]{1}[0-9]{1})$

evaluation expression reguliere


Passons aux tests:

Tests ftp-proxy

Tests FTP

1) Depuis mon poste de travail je me connecte sur le serveur maitre:

pme@pme-linux:~$ ftp 192.168.1.241
Connected to 192.168.1.241.
220 srvglus238 FTP server (Version 1.9.2.4 - 2005/01/11 13:03:28) ready.
Name (192.168.1.241:pme): ftpsrvglus238@192.168.1.241:2121
331 User ftpsrvglus238 OK. Password required
Password:
230-User ftpsrvglus238 has group access to:  1004   
230 OK. Current directory is /
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -l
200 PORT command successful.
150 Connecting to port 42787
drwxr-s---    9 1004     33           4096 May 20 09:09 .
drwxr-s---    9 1004     33           4096 May 20 09:09 ..
-rw-r--r--    1 0        33        3935995 May 20 09:05 cl1811.tgz
-rw-r--r--    1 0        0         4611614 May 20 08:38 cl190.tgz
drwxr-s---    6 1004     33           4096 Dec 15 10:36 jy03
drwxr-xr-x   10 1004     33           4096 Mar 20 11:34 ldapadmin
drwxr-s---    5 1004     33           4096 Jan 27 14:10 log2524
drwxr-s---   16 1004     33           4096 Mar 17 10:10 npds
-rw-r--r--    1 1004     33          37806 Apr  6 16:19 php.ini
-rw-r--r--    1 1004     33             18 Dec 11 17:53 phpinfo.php
-rw-r--r--    1 0        33        6713658 May 20 08:16 pmenier-stud.tgz
drwxr-s---   15 1004     33           4096 Apr 27 12:23 spip
drwxr-s---    3 1004     33           4096 Mar 17 09:17 src
drwxr-s---   15 1004     33           4096 May 20 09:03 student
226-Options: -a -l
226 14 matches total
ftp> quit
221 Goodbye.


2) Depuis mon poste de travail je me connecte sur le vserver 1

pme@pme-linux:~$ ftp 192.168.1.241
Connected to 192.168.1.241.
220 srvglus238 FTP server (Version 1.9.2.4 - 2005/01/11 13:03:28) ready.
Name (192.168.1.241:pme): ftpweb1@192.168.1.242
331 Password required for ftpweb1
Password:
230 User ftpweb1 logged in
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -l
200 PORT command successful.
150 Opening ASCII mode data connection for file list
lrwxrwxrwx   1 root     root           14 Oct 15  2008 doc -> /usr/share/doc
-rw-r--r--   1 root     root         2129 Mar 23 13:16 index.html
drwxr-xr-x   2 root     root         4096 Mar 23 13:10 named
drwxr-xr-x   2 root     root         4096 Mar 23 13:16 passivedomains
lrwxrwxrwx   1 root     root           21 Mar 23 13:13 phpmyadmin -> /usr/share/phpmyadmin
lrwxrwxrwx   1 root     root           11 Oct 15  2008 share -> /usr/share/
drwxr-xr-x   5 root     root         4096 Mar 23 13:34 vhosts
drwxr-xr-x   2 root     root         4096 Apr 12 04:25 webalizer
226 Transfer complete
ftp> quit
221 Goodbye.

3) Depuis mon poste de travail je me connecte sur le vserver 5

pme@pme-linux:~$ ftp 192.168.1.241
Connected to 192.168.1.241.
220 srvglus238 FTP server (Version 1.9.2.4 - 2005/01/11 13:03:28) ready.
Name (192.168.1.241:pme): ftpweb5@192.168.1.250
331 Password required for ftpweb5
Password:
230 User ftpweb5 logged in
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
200 PORT command successful.
150 Opening ASCII mode data connection for file list
drwxr-xr-x   2 ftpweb5  ftpweb5      4096 May 26 07:54 .
drwxr-xr-x   7 root     root         4096 May 26 07:54 ..
-rw-r--r--   1 ftpweb5  ftpweb5       220 May 26 07:54 .bash_logout
-rw-r--r--   1 ftpweb5  ftpweb5      3116 May 26 07:54 .bashrc
-rw-r--r--   1 ftpweb5  ftpweb5       675 May 26 07:54 .profile
226 Transfer complete
ftp> quit
221 Goodbye.

4) Depuis mon poste de travail j'essaie de me connecter sur free en passant par mon serveur:

pme@pme-linux:~$ ftp 192.168.1.241
Connected to 192.168.1.241.
220 srvglus238 FTP server (Version 1.9.2.4 - 2005/01/11 13:03:28) ready.
Name (192.168.1.241:pme): xxxxx@ftpperso.free.fr

421 Service not available, remote server has closed connection


C'est bon. On passe à apache.


Configuration pound


J'ai donc déclaré un domaine srvglus238.net.pat pointant sur /var/www/srvglus et un autre domaine mailman.net.pat pointant sur /var/www/mailman sur le serveur maître et un autre domaine vweb1.domaine.pat pointant sur /var/www/ dans le vserver 1.

Config du vhost srvglus238.net.pat sur le maître:

srvglus238:/etc/apache2/sites-enabled# cat srvglus
<VirtualHost 192.168.1.241:8080>
    ServerAdmin webmaster@localhost
        suPHP_ConfigPath "/var/www/srvglus"
        suPHP_UserGroup client1 www-data 
    DocumentRoot /var/www/srvglus
    ServerName srvglus238.net.pat
    <Directory /var/www/srvglus>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
    </Directory>
    ErrorLog /var/log/apache2/error.log
    LogLevel warn
    Alias /doc/ /usr/share/doc/
    CustomLog /var/log/apache2/access.log combined
    ServerSignature On
</VirtualHost>

Le vhost mailman est pratiquement identique à l'exception de quelques directives: suPHP_UserGroup, DocumentRoot, ServerName.

Extrait des lignes intéressantes du fichier /etc/apache2/apache2.conf:

srvglus238:/etc/apache2# egrep 'NameVirtual|sites-enabled' apache2.conf
NameVirtualhost 192.168.1.241:8080
Include /etc/apache2/sites-enabled/

Sur le vserver 1:

vweb1:/etc/apache2/sites-enabled# cat 000-default
NameVirtualHost *
<VirtualHost *>
ServerName vweb1.domaine.pat
DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options -Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
LogLevel debug
CustomLog /var/log/apache2/access.log combined
</VirtualHost>

vweb1:/etc/apache2# egrep 'NameVirtual|Log' apache2.conf
ErrorLog /var/log/apache2/error.log
LogLevel warn
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent


En ce qui concerne pound (qui a été installé par : apt-get install pound), il n'y a qu'un seul et unique fichier de config sur le serveur maître

srvglus238:/etc/pound# cat pound.cfg |egrep -v '^#|^$'
User        "www-data"
Group        "www-data"
LogLevel    2
Alive        30
Control "/var/run/pound/poundctl.socket"
ListenHTTP
    Address 192.168.1.241
    Port    80
    ## allow PUT and DELETE also (by default only GET, POST and HEAD)?:
    xHTTP        0
    Service
        HeadRequire "Host: srvglus238.net.pat"
        BackEnd
            Address    192.168.1.241
            Port    8080
        End
    End
        Service
        HeadRequire "Host: vweb1.domaine.pat"
                BackEnd
                        Address 192.168.1.242
                        Port    80
                End
        End
        Service
        HeadRequire "Host: mailman.net.pat"
                BackEnd
                        Address 192.168.1.241
                        Port    8080
                End
        End
End


Passons aux tests:

Tests pound


Je lance mon browser sur http://vweb1.domaine.pat

pound apache2 proxy



Puis je le lance sur: http://srvglus238.net.pat

pound apache2 proxy


C'est bon bien que les 2 serveurs soient sur des ip différentes et sur des ports différents.


Voilà c'est fini :)  J'insiste encore une fois sur le fait qu'avant de mettre une telle config en prod il faudra tester mais après tout c'est ce que l'on fait toujours non ?