Debian logo [inetdoc.LINUX]

4. Echanges avec le protocole TFTP

Le protocole TFTP est défini dans le document RFC1350 The TFTP Protocol (Revision 2). C'est un protocole très simple utilisé pour transférer des fichiers. Il s'appuie sur le protocole UDP au niveau transport. Ce protocole est limité à l'écriture et à la lecture de fichiers entre deux hôtes réseau. Il ne possède pas de fonction d'authentification et il est impossible de lister les fichiers à distance.

L'absence de complexité de ce protocole fait qu'il est implantable dans un espace mémoire réduit. C'est la raison pour laquelle on le retrouve dans la majorité des équipements réseau comme moyen d'échange d'images firmware des systèmes d'exploitation (et|ou) de fichiers de configuration.

Dans le contexte de ce document, le poste avec le système GNU/Linux doit échanger les fichiers avec l'équipement réseau. Il s'agit donc de configurer un service tftpd avec un minimum de précautions au niveau sécurité.

4.1. Installation et configuration du service tftpd

Comme indiqué dans la Section 1.3, « Logiciels utilisés », seuls les paquets de la distribution Debian GNU/Linux sont présentés ici. À l'heure actuelle, la distribution comprend trois paquets de service tftpd. Les opérations présentées ci-après utilisent le paquet historique GNU/Linux tftpd qui convient parfaitement aux traitements courants. Ce paquet est cependant limité au niveau de la taille des fichiers échangés. Pour les fichiers volumineux tels que les images de système d'exploitation (firmware), il est préférable d'utiliser le paquet tftpd-hpa. L'installation et la configuration du paquet tftpd-hpa est en tout point identique à celle du paquet tftpd.

L'installation de tftpd se résume à l'intruction suivante :

# apt-get install tftpd

Après cette étape triviale, il faut configurer le service. tftpd ne possédant aucune fonction de contrôle d'accès, celles ci sont prises en charge par le «super-démon» inetd dont le fichier de configuration contient une ligne par service géré.

Fichier /etc/inetd.conf

Extrait du fichier inetd.conf relatif à tftpd :

#:BOOT: Tftp service is provided primarily for booting.  Most sites
# run this only on machines acting as "boot servers."
tftp   dgram   udp     wait    nobody  /usr/sbin/tcpd  /usr/sbin/in.tftpd /boot

Contrairement à ce qui est annoncé dans les lignes de commentaires, le service ne sert pas principalement au démarrage machine mais aux échanges de fichiers en cours de fonctionnement.

Répertoire /srv/tftp

Comme sur un système GNU/Linux le répertoire /boot contient les images de noyau Linux, il est préferrable de créer un nouveau répertoire pour le service tftpd. On évite ainsi un «mélange des genres» douteux.

On commence par modifier la ligne du fichier inetd.conf comme ci-dessous :

tftp   dgram   udp     wait    nobody  /usr/sbin/tcpd  /usr/sbin/in.tftpd /srv/tftp

On créé ensuite le répertoire /srv/tftp en lui appliquant un masque de permissions adapté :

# mkdir -p /srv/tftp
# chmod 1777 /srv/tftp
# ls -ld /srv/tftp/
drwxrwxrwt  2 root root 4096 2005-01-09 17:58 /srv/tftp/

Le masque de permission appliqué au répertoire utilise le directory sticky bit pour que tous les utilisateurs du système puissent y placer des fichiers.

Enfin, on relance le service inetd pour que les changements soient pris en compte et on vérifie que le service est actif.

# /etc/init.d/inetd restart
Restarting internet superserver: inetd.
:~# lsof -i |grep tftp
inetd    10535        root    5u  IPv4  19054       UDP *:tftp
Contrôle d'accès

Le fait que le service tftpd soit actif n'est pas suffisant. Il faut autoriser l'accès à ce service. C'est le rôle du tcpwrapper qui assure le contrôle d'accès pour les services qui ne possèdent pas cette fonction.

La gestion du contrôle d'accès se fait à l'aide des fichiers /etc/hosts.allow et /etc/hosts.deny. Ces deux fichiers permettent d'appliquer la politique de sécurité classique : «tout ce qui n'est pas explicitement autorisé est interdit».

Le fichier /etc/hosts.deny contient donc une instruction unique d'interdiction d'accès depuis les réseaux externes : ALL: PARANOID EXCEPT 127.0.0.1.

Dans le cas illustré dans ce document, il s'agit d'autoriser l'accès aux hôtes du réseau d'infrastructure des équipements réseau (192.168.2.0/24 par exemple). On édite le fichier /etc/hosts.allow en ajoutant l'accès au service tftpd depuis ce réseau :

# /etc/hosts.allow: list of hosts that are allowed to access the system.
#                   See the manual pages hosts_access(5), hosts_options(5)
#                   and /usr/doc/netbase/portmapper.txt.gz
#
# Example:    ALL: LOCAL @some_netgroup
#             ALL: .foobar.edu EXCEPT terminalserver.foobar.edu
#
# If you're going to protect the portmapper use the name "portmap" for the
# daemon name. Remember that you can only use the keyword "ALL" and IP
# addresses (NOT host or domain names) for the portmapper, as well as for
# rpc.mountd (the NFS mount daemon). See portmap(8), rpc.mountd(8) and
# /usr/share/doc/portmap/portmapper.txt.gz for further information.
#
in.tftpd: 192.168.2.0/24

Enfin, on vérifie que les accès sont bien ouverts :

# tcpdchk -v
Using network configuration file: /etc/inetd.conf

>>> Rule /etc/hosts.allow line 14:
daemons:  in.tftpd
clients:  192.168.2.0/24
access:   granted

>>> Rule /etc/hosts.deny line 20:
daemons:  ALL
clients:  PARANOID EXCEPT 127.0.0.1
access:   denied

4.2. Exemples d'utilisation du service tftpd

4.2.1. Mise à jour système d'un routeur Cisco 2851

Dans ce cas de figure, le transfert se fait du poste GNU/Linux vers l'équipement. Il n'y a donc aucun problème lié aux accès sur le système de fichiers côté GNU/Linux. Il suffit de placer une copie du fichier à transférer dans le répertoire /srv/tftp/.

Cet exemple est particulier puisque la taille du fichier image du système d'exploitation est importante. Le service tftpd est assuré à partir du paquet tftp-hpa qui autorise le transfert de blocs de données importants.

$ cd /srv/tftp
$ ll c2800nm-advipservicesk9-mz.124-11.T1.bin
-rw-r--r-- 1 user adm 38M 2007-03-20 21:10 c2800nm-advipservicesk9-mz.124-11.T1.bin

Côté routeur, il faut s'assurer que la mémoire flash dispose d'un espace libre suffisant pour acceuillir la nouvelle image du système d'exploitation IOS. Au besoin, il faut effacer le fichier image en cours d'exécution.

router#sh flash:
-#- --length-- -----date/time------ path
1         1826 Jul 5 2006 23:53:52 +02:00 sdmconfig-28xx.cfg
2      4734464 Jul 5 2006 23:54:12 +02:00 sdm.tar
3       833024 Jul 5 2006 23:54:26 +02:00 es.tar
4      1052160 Jul 5 2006 23:54:40 +02:00 common.tar
5         1038 Jul 5 2006 23:54:54 +02:00 home.shtml
6       102400 Jul 5 2006 23:55:06 +02:00 home.tar
7       491213 Jul 5 2006 23:55:18 +02:00 128MB.sdf
8      1684577 Jul 5 2006 23:55:38 +02:00 securedesktop-ios-3.1.1.27-k9.pkg
9       398305 Jul 5 2006 23:55:56 +02:00 sslclient-win-1.1.0.154.pkg

54702080 bytes available (9314304 bytes used)

On lance le transfert en indiquant le fichier image sur le serveur TFTP comme source et la mémoire flash comme destination.

router#copy tftp://192.168.2.1/c2800nm-advipservicesk9-mz.124-11.T1.bin flash:
Destination filename [c2800nm-advipservicesk9-mz.124-11.T1.bin]?
Accessing tftp://192.168.2.1/c2800nm-advipservicesk9-mz.124-11.T1.bin...
Loading c2800nm-advipservicesk9-mz.124-11.T1.bin from 192.168.2.1 \
		(via GigabitEthernet0/1): !!!!!!!!!!!!!!!!!!
<snip/>

[OK - 39798360 bytes]

39798360 bytes copied in 580.728 secs (68532 bytes/sec)

router#sh flash:
-#- --length-- -----date/time------ path
1         1826 Jul 5 2006 23:53:52 +02:00 sdmconfig-28xx.cfg
2      4734464 Jul 5 2006 23:54:12 +02:00 sdm.tar
3       833024 Jul 5 2006 23:54:26 +02:00 es.tar
4      1052160 Jul 5 2006 23:54:40 +02:00 common.tar
5         1038 Jul 5 2006 23:54:54 +02:00 home.shtml
6       102400 Jul 5 2006 23:55:06 +02:00 home.tar
7       491213 Jul 5 2006 23:55:18 +02:00 128MB.sdf
8      1684577 Jul 5 2006 23:55:38 +02:00 securedesktop-ios-3.1.1.27-k9.pkg
9       398305 Jul 5 2006 23:55:56 +02:00 sslclient-win-1.1.0.154.pkg
10    39798360 Mar 24 2007 17:04:52 +01:00 c2800nm-advipservicesk9-mz.124-11.T1.bin

14901248 bytes available (49115136 bytes used)

4.2.2. Mise à jour système d'un commutateur Cisco 2950

Comme dans l'exemple précédent, le transfert se fait du poste GNU/Linux vers l'équipement et le fichier à transférer est dans le répertoire /srv/tftp/.

Côté équipement, il faut un minimum de configuration réseau IP pour communiquer avec le poste GNU/Linux.

sw1#sh run
Building configuration...
<snip/>
!
interface Vlan1
 no ip address
 no ip route-cache
 shutdown
!
interface Vlan2
 ip address 192.168.2.2 255.255.255.0
 no ip route-cache
!

On peut ensuite lancer le transfert à partir de l'interface de commande de l'équipement. Voici un exemple de mise à jour via tftpd :

sw1#archive tar /x tftp://192.168.2.1/c2950-i6q4l2-tar.121-22.EA2.tar flash:

L'accès à l'interface de commande de l'équipement réseau peut être obtenu à l'aide de minicom ou de telnet.

4.2.3. Sauvegarde de la configuration d'un équipement

Ici, le transfert se fait depuis l'équipement réseau vers le poste GNU/Linux sur lequel le service tftpd est exécuté.

Avant de lancer le transfert du fichier de configuration, il est nécessaire de donner les droits d'accès au fichier sur le système GNU/Linux. En reprenant l'exemple du commutateur 2950, voici la marche à suivre :

$ touch /srv/tftp/sw1-confg
$ chmod 666 /srv/tftp/sw1-confg

Une fois ces opérations effectuées, on peut lancer le transfert de la configuration de l'équipement.

sw1#copy run tftp://192.168.2.1
Address or name of remote host [192.168.2.1]?
Destination filename [sw1-confg]?
!!
2748 bytes copied in 1.116 secs (2462 bytes/sec)

Dans les faits, cette manipulation n'a lieu qu'une fois : lors de l'installation d'un nouvel équipement. Par la suite, il est beaucoup plus fréquent que l'on édite la configuration sur le poste GNU/Linux avant de la transférer vers l'équipement. Cette méthode permet d'assurer un suivi des évolutions de configuration via un système de contrôle de version tel que CVS. On dispose ainsi d'un dépôt centralisé des configurations.

4.2.4. Mise à jour de la configuration d'un équipement

On retrouve dans ce cas un transfert depuis le poste GNU/Linux vers l'équipement réseau. C'est le cas le plus simple du point de vue de la gestion des droits.

Une fois la nouvelle configuration éditée, on place le fichier correspondant dans le répertoire /srv/tftp/ et on lance le transfert à partir de l'interface de commande de l'équipement.

sw1#copy tftp://192.168.2.1/new-confg run
Destination filename [running-config]?
Accessing tftp://192.168.2.1/new-confg...
Loading new-confg from 192.168.2.1 (via Vlan2): !
[OK - 2756 bytes]

2756 bytes copied in 19.984 secs (138 bytes/sec)
sw1#
2d00h: %SYS-5-CONFIG_I: Configured from tftp://192.168.2.1/new-confg by console
sw1#
<snip/>

sw1#copy run start
Destination filename [startup-config]?
Building configuration...
[OK]

Il est préferable de copier la configuration en RAM dans un premier temps. Si la nouvelle configuration provoque un dysfonctionnement réseau, on a toujours la possibilité de réinitialiser complètement l'équipement. Il reprendra la configuration stockée en NVRAM (la version correcte précédente). Autrement, après avoir effectué les tests d'usage, on sauvegarde la nouvelle configuration en RAM dans la NVRAM.

4.3. Un soupçon de sécurité

Comme le service tftpd n'est pas un modèle en matière de sécurité, il est souhaitable de bien encadrer son utilisation. Généralement, on complète le contrôle d'accès (voir Contrôle d'accès) par une règle de filtrage réseau pour chaque équipement.

Côté équipement on fixe l'adresse IP ou l'interface utilisée pour les transactions TFTP avec des instructions du type :

  • Pour un commutateur :

    interface Vlan2
      ip address 192.168.2.2 255.255.255.0
      no ip proxy-arp
      no ip route-cache
    !
    ip tftp source-interface Vlan2
    
  • Pour un routeur :

    interface Loopback0
      ip address 192.168.2.2 255.255.255.255
      no ip redirects
      no ip unreachables
      no ip directed-broadcast
      no ip proxy-arp
    !
    ip tftp source-interface Loopback0
    

Côté service tftpd, on n'autorise les accès TFTP (port 69/udp) qu'à partir des adresses IP fixées sur les équipements. Voici un extrait du fichier /var/lib/iptables/active utilisé par le script d'initialisation du paquet iptables.

*filter
:INPUT DROP [0:0]
<snip/>
-A INPUT -s 192.168.2.2 -p udp --dport 69 -m state --state NEW -j ACCEPT
<snip/>

Pour un exemple complet, voir Annexe A, Configuration type du filtrage réseau.