Implementing a simple RMI Application over the Internet (using and

publicité
Implementing a simple
RMI Application over the
Internet
(using and comparing HTTP tunneling, RMI Proxy)
Plan de l ’exposé



Introduction
Problématique
HTTP tunneling
• Comment RMI « tunnelle » des messages
• Stratégie utilisée pour une invocation de méthode sur un
serveur
• Naming Services
• L’implémentation d’un servlet pour le HTTP Tunneling
• Modifications à apporter au code afin d’utiliser le HTTP
Tunneling
• Configuration du fichier policy
• Exemple de requête RMI
Plan de l ’exposé (2)

RMI Proxy
• Les objectifs
• Les caractérisitiques
• Le contrôle d’accès
• L’architecture
• Fonctionnement de RMI Proxy
• L’API côté client et serveur
• Limitations du RMI Proxy
• Les modifications à apportées au client et au serveur
• Les différences entre RMI Proxy et HTTP Tunneling

Conclusion
Introduction

RMI (Remote Method Invocation)
• est un système distribué
• une ou plusieurs applications peuvent s’exécuter sur une ou
plusieurs machines
• Aucun problème s’il n’y a aucun firewall entre les deux parties
communiquantes
Problématique

Le problème principal
lorsqu’un client veut effectuer un appel RMI sur une machine
distante est le firewall.


Firewalls interdisent souvent l’accès
à certains ports spécialisés comme
ceux qu’on désire utiliser lors d’un
appel RMI.
Solution
techniques de tunneling, RMI Proxy ou encore d’autres
peuvent être utilisées.
HTTP Tunneling

Principe de base

Évite les firewalls

Principe
Utiliser comme protocole de communication des appelles http à
travers le Web
en utilisant le port HTTP (80), celui-ci n’est en général pas boqué
par le firewall et le firewall ne peut pas prendre de décisions en
fonction du contenu des paquets.
Le client utilise une couche supplémentaire (marshalling layer) qui
encode la requête RMI du client en une requête HTTP valide.
Le serveur de l’autre coté comprend aussi une couche
supplémentaire (layer of demarshalling code), laquelle transforme
une requête HTTP en une requête correspondant à celle attendue
par le serveur (dans ce cas un requête RMI).
HTTP Tunneling (2)




Le HTTP tunneling est divisé en trois
parties :
Le Client
Envoie une requête au serveur web
Le servlet
Transmet la requête à la socket du serveur RMI en
préservant la structure HTTP qui a été envoyée par le client
Le serveur
Transforme automatiquement l’envoi HTTP en une
commande JRMP
HTTP Tunneling (3)
Comment RMI « tunnelle » des
messages

But du mécanisme de RMI’s HTTP
tunneling : encode un appel de méthode à distance
à la façon d ’une requête POST et ensuite décode la « page
web » retournée.


RMI utilise son propre mode de
socket (RMIHttpToCGISocketFactory()) quand
des connections sont créées.
Ces sockets tentent d’utiliser HTTP
tunneling si auparavant elles ont
reçu une erreur du serveur.
Stratégie utilisée pour une invocation de
méthode sur un serveur


Tentent d’établir une connexion JRMP
(Java Remote Method Invocation) directe
vers le serveur.
établir une connexion HTTP directe avec
le serveur. Ainsi elles créent une
connexion par socket vers le port sur
lequel le serveur est en train d’écouter et
ensuite communique en encapsulant les
méthodes demandées dans des requêtes
HTTP.
Stratégie utilisée pour une invocation
de méthode sur un serveur (2)
• Utilise le firewall comme un serveur proxy (demandant
au firewall de transmettre la requête au port approprié
du serveur). Le firewall transmettra la requête comme
une requête HTTP (le firewall ne va pas traduire la
requête en appel RMI).
• Se connecte sur le port 80 de la machine serveur et lui
envoie la requête selon un URL commençant avec /cgibin/java-rmi.cgi. Cet URL signifie que la requête doit
être transmise vers un programme qui interprète les
requêtes HTTP et qui la transmet, comme une requête
HTTP, vers le port approprié du serveur.

Chaqu’un de ces points a son sens, la connexion
est établie selon les privilèges que le firewall
accorde.
Naming Services


La machine serveur dans la quatrième
option est une abstraction, elle n’a pas
besoin d’être sur la même machine que
l’objet serveur RMI. Permet donc plus de
flexibilité au HTTP Tunneling.
Pour ce faire nous devons écrire un servlet
qui effectue la redirection de la requête
RMI vers le serveur RMI, ensuite le
serveur web est configuré pour envoyer
toutes les requêtes avec l’URL approprié.
Naming Services (2)
L’implémentation d’un servlet pour
le HTTP Tunneling

La première implémentation, qui permet de
transmettre l’invocation de méthodes au serveur
RMI, que Sun Microsystems, Inc. Développa était
un script CGI (java-rmi.cgi)

Chaque invocation distante de méthodes est envoyée
comme une requête HTTP POST

L’URL complet utilisé est de la forme


/cgi-bin/java-rmi.cgi ?forward=[port number]
Le corps du POST contient toutes les données de la
requête distante comme un objet sérialisé qui est
ensuite convertit en une chaîne de caractères ASCII.
Sun créa ensuite un servlet qui fournit les mêmes
fonctionnalités que le script CGI.
Le code du servlet

Deux classes principales
SimplifiedServletHandler et ServletForwardCommand

SimplifiedServletHandler
Cette classe étend HTTPServlet. Elles reçoit les requêtes et
effectue un validation préliminaire.

ServletForwardCommand
C’est une liste de méthodes statiques qui sait comment
interpréter un HTTP POST et renvoyer ceci au serveur Rmi
qui tourne sur la même machine.
Le code du servlet (2)

Explication d’une partie de code de
SimplifiedServletHandler
• Des testes sont effectués afin de contrôlé la validité de
l’URL et présence du port, la requête est ensuite
transmise à la méthode statique execute()

if (command.equalsIgnoreCase("forward")) {
try {
LoggingServletForwardCommand.execute(req, res, param);
} catch (ServletClientException e) {
returnClientError(res, "client error: " + e.getMessage());
e.printStackTrace();
} catch (ServletServerException e) {
returnServerError(res, "internal server error: " + e.getMessage());
e.printStackTrace();
}
} else {
returnClientError(res, "invalid command: " + command);
}
Le code du servlet (3)



Explication d’une partie du code de
ServletForwardCommand
on utilise des sockets pour transmettre le corps du message HTTP
au serveur RMI et ensuite des simples « pipes » que le serveur
RMI pour retourner des sortis de type HttpServletResponse
(response).
ServletForwardCommand transmet le message sans décoder les
données ou comprendre le message
•
•
socketOut = new
DataOutputStream(connectionToLocalServer.getOutputStream());
socketOut.writeBytes("POST / HTTP/1.0\r\n");
socketOut.writeBytes("Content-length: " + request.getContentLength() +
"\r\n\r\n");
socketOut.write(buffer);
socketOut.flush();
OutputStream out = response.getOutputStream();
out.write(buffer);
out.flush();
Modifications à apporter au code
afin d’utiliser le HTTP Tunneling


La socket RMI par défaut tentera automatiquement
d’utiliser le HTTP tunneling quand les autres connexions
auront échouées.
On ne change ni le code du serveur ni le code du
client, on ajoute simplement un ligne dans le
code du client afin qu’il puisse utiliser le HTTP
tunneling.
RMISocketFactory.setSocketFactory(new sun.rmi.transport.proxy.RMIHttpTOCGISocketFactory()) ;
Configuration du fichier policy


Chaque servlet est obligatoirement exécutée sous
le contrôle d’un gestionnaire de sécurité.
Les politiques de sécurité appliquées par la JVM
ne permettent pas du téléchargement de code
sans permission explicite. Donc dans le fichier
policiy du client et du serveur les permissions
suivantes doivent être ajoutées :
•
•

permission java.net.SocketPermission "*:1024-65535","connect,accept";
permission java.net.SocketPermission "*:80", "connect";
Chez le client il y a encore une permission de
plus affin que celui-ci puisse utiliser la
« RMISocketFactory » :
•
permission java.lang.RuntimePermission "setFactory";
Exemple de requête RMI
Seconde technique
RMI Proxy
Les objectifs






Eliminer les problèmes de sécurités de RMI à
travers HTTP pour l’administrateur réseau, via
une application firewall qui ne supporte
uniquement le protocole RMI/JRMP.
Réduction des overhead comparé au HTTP
tunneling lors du passage à travers un firewall.
Permettre un accès contrôlé des appels du coté
client derrière un firewall.
Préserver toutes les propriétés de RMI
Requérir un minimum de modifications de code
chez le client et le serveur RMI
Reprendre le maximum d’avantages existants
dans les classes java.
Les caractéristiques


RMI Proxy est une application Java et une API
permettant le contrôle de la pénétration dans un
firewall en approuvant les clients et les serveurs
RMI.
RMI Proxy est capable de:
• Bloquer l’accès aux protocoles non-JRMP
• Contrôler les écritures vers la RMI Proxy Registry selon
l’identification de l’hôte client
• Permettre ou refuser l’accès et l’exécution de méthodes
distantes au client RMI, selon l’identificateur de l’hôte
client.
• Permettre ou refuser le transfert de code par le service
du codebase RMI, dans les deux directions
Le contrôle d’accès



Il est fournit par les fichiers Java policy, lesquels
contrôle la communication à travers les firewalls.
Le contrôle d’accès s’effectue selon l’adresse IP
ou le nom du client voulant passer le firewall et
de l’action qu’il veut effectuer. Classe spécialisée
: « FirewallPermission »
Le contrôle est capable d’être contre les actions
suivantes :
•
•
•
•
L’accès à certain objet
Bind, rebind ou unbind certain nom
L’exécution de certaines méthodes distantes
Chercher certains noms dans la proxy registry
L’architecture

Composants importants :
• Le programme RMI Proxy, lequel s’exécute dans les
machines proxy désignées.
• La classe ProxyNaming, une classe Naming modifiée,
appelée par les clients et serveurs RMI.

Sous-composants
• La proxy registry

RMI registry normale qui est soumise aux règles de
contrôles d’accès fournis par l’implémentation du serveur
RMIProxy
• Un protocole RMI

négocie entre les flux descendants du serveur RMI et les
flux montants du client RMI, effectuant la validation du
protocole et le contrôle d’accès dans le processus
Fonctionnement de RMI Proxy




Pour le client RMI, une
opération « lookup » sur un
objet distant doit être dirigée
vers le serveur proxy.
Si le client est aussi lui-même
derrière un firewall, le
« lookup » est délégué à son
RMI Proxy.
La partie extérieur du proxy
du client est capable de
communiquer par RMI avec la
partie extérieur du proxy
serveur.
Les proxies RMI servent
d’intermédiaires entre les
entrés vers le serveur et les
sorties du client.
RMI Proxy (2)


Le RMI proxy Registry
et les composants
serveur sont installés
en association avec
chaque firewall qui
existe entre le client
RMI et le serveur RMI.
Chacun doit ouvrir un
port au trafique RMI,
lequel est ensuite
manipulé d’un
manière sécurisée par
le RMI proxy associé.
L’API côté client et serveur


Le client est derrière plusieurs firewall -> délègue le lookup au
proxy final coté client (grace à la propriété rmi.proxyHost) puis
un stub est obtenu.
Le serveur exécute un bind dans la chaîne de registry des proxy
en déléguant le bind. Il est donc lié à la registry locale et aux
registry de toute la chaîne des proxy
Limitations du RMI Proxy

Activation
• L’implémentation actuelle réécrit les stubs activables comme
des stubs unicast normaux

Stubs cachés
• N’effectue pas d’arrangement proxying pour les stubs cachés
(Stubs à l’intérieur de MarshalledObjects)

Socket Factories
• Socket factories ne sont actuellement pas supportées

GetClientHost
• RmoteServer.getClientHost retourne l’InetAddress du RMI
Proxy le plus proche et non le vrai client RMI

RMI/IIOP (Internet Inter-Orb Protocol)
• Ne supporte pas les stubs RMI/IIOP

Stubs distants indirectes
• Petite modification nécessaire dans la classe
sun.rmi.MarshalOutputStream pour traiter les stubs distants
indirectes
Les modifications à apportées au
client et au serveur

Du coté serveur la classe com.rmiproxy.ProxyNaming doit
être utilisée à la place de la classe java.rmi.Naming.

Exemple de code :
ProxyNaming.bind(« rmi://localhost/ » + RemoteEcho.class.getName()) ;

Du coté client le même principe doit être utilisé on
remplace la classe java.rmi.Naming par la classe
com.rmiproxy.ProxyNaming.

Exemple de code :
RemoteEcho echoObject =
(RemoteEcho)ProxyNaming.lookup(« rmi://rmi.server.com/ »
+RemoteEcho.class.getName()) ;

Définir les propriétés du système rmi.proxyHost

Exemple
Rmi.proxyHost=rmi://proxy.clientlan0.client.com


:
Configurer le fichier policy du client et du serveur.
Installer ProxyBoot.jar, ProxyMain.jar et RMIProxy.policy sur
chaque machine proxy.
Les différences entre RMI Proxy et
HTTP Tunneling
HTTP tunneling
RMI Proxy
Il n’est pas très fiable. Si on modifie le
firewall il est possible que le tunneling ne
fonctionne plus.
Plus robuste au changement du firewall.
Ces performances sont faibles.Il encode
beaucoup d’informations dans chaque
message de requête. Il doit créer une
nouvelle socket pour chaque requête qu’il
effectue.
Les requêtes sont des requêtes RMI sans
information supplémentaire.
Il ne fonctionne pas à travers tous les types
de firewall.
Fonctionne avec tout type de firewall.
Inefficacité de la connexion, il ne peut pas
créer un connexion et la laisser ouverte pour
pouvoir la réutiliser, il doit créer une
nouvelle socket pour chaque requête qu’il
effectue.
Connexion ne se referme pas après
chaque requête.
Conclusion

Le RMI Proxy est certainement une méthode
bien meilleur que le HTTP tunneling, car elle
ne comporte que des avantages sur cette
dernière.
QUESTION?
Téléchargement