Outils pour utilisateurs

Outils du site


papweb

Ceci est une ancienne révision du document !


Configuration d'un Point d'Accés Public au Web

Objectifs

Mettre à la disposition du public des lieux publics (MPT, MJC, Associations, etc…) des bornes d'accès au web Recycler des ordinateurs anciens en installant une distribution légère de GNU/Linux qui proposera aux utilisateurs un seul logiciel : le navigateur Web1)

Installation de l'OS

Comme OS on part sur une base de Debian/Squeeze que l'on installera seuelement avec le système de base et openssh.

On fera 4 partitions2): * le swap * la racine (/) * le home (/home) * les logs et autre données du système (/data)

On peut créer ou pas l'utilisateur à ce moment mais faudra penser à restreindre ses droits dans le fichier /etc/group.

Configuration de l'OS
# mkdir /data/log
# echo "/data/log /var/log none bind 0 0" >> /etc/fstab
# mkdir /root/.ssh && chmod 700 /root/.ssh
# touch /root/.ssh/authorized_keys

Copiez vos clés id_rsa.pub dans le fichier /root/.ssh/authorized_keys puis éditez le fichier /etc/ssh/sshd_config pour les authentification par mot de passe et n'autoriser que l'ulisateur root à se connecter:

PasswordAuthentication no
AllowUsers root

Puis on verrouille le compte root. Tous les accés suivants au compte root se faisant par ssh.

# passwd -l

On vérifie le fichier /etc/network/interfaces

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

Attention au fichier /etc/resolv.conf. Il doit contenir la même liste de nameserver que l'endroit ou sera placer la machine ou utiliser un serveur DNS public comme 8.8.8.8.

On complète le fichier /etc/apt/sources.list

deb http://ftp.fr.debian.org/debian squeeze main contrib non-free

deb http://ftp.fr.debian.org/debian/ squeeze-updates main contrib non-free

deb http://security.debian.org/ squeeze/updates main contrib non-free

# Pour avoir xulrunner-2.0 et iceweasel-4.0 sur squeeze
deb http://mozilla.debian.net/ squeeze-backports iceweasel-4.0

En fonction du matériel présesent dans la machine il peut être nécessaire d'avoir les firmwares:

# apt-get install firmware-linux

Si d'autre firmware doivent être installé, on a la list avec:

# apt-cache search --names-only firmware

On ajoute le support acpi et la gestion du son avec alsa3)

# apt-get install acpi acpi-support acpitool alsa-base alsa-firmware-loaders alsa-tools alsa-utils

Editez le fichier /etc/modprobe.d/alsa-base-blacklist.conf pour backlister les modules snd-pcsp et pcspkr pour arretez les BEEPs.

installation du proxy

Le proxy ainsi que l'écriture des logs ne devrait pas être sur ce type machine mais placé sur un serveur différent. Le choix du proxy et de ses modules complémentaires dépend de ce qui doit être filtré. Là on va juste installer squid et adzapper pour filtrer la pub:

# apt-get install squid adzapper

Puis il faut ajouter la ligne

redirect_program /usr/bin/adzapper

au fichier /etc/squid/squid.conf

Configuration de l'espace utilisateur

Créez l'utilisateur si il n'a pas été créé lors de l'installation. On va l'appeler linuxquimper. Il doit appartenir aux groupes video et audio (voir /etc/group). Puis il faut faire une sauvegarde du compte et on le verouille:

# rsync -av /home/linuxquimper /opt/
# passwd -l linuxquimper

On ajoute le serveur X et le gestionnaire de connection automatique nodm:

# apt-get install xorg nodm
Choix du navigateur

C'est ce qui pose le plus problème car on ne peut pas installer n'mporte quel navigateur. Celui-ci doit avoir les fonctionnalitées suivantes: * pas d'accés aux systèmes de fichiers * pas d'ouverture de nouvelles fenêtres car on n'install pas de window manager * support des onglets * support de l'html5 avec les balises video, audio et mathml * support optionnel des plugins pour avoir flash, la lecture de fichier pdf ou autres document bureautique directement dans le navigateur.

Actuellement, il n'existe pas pas de navigateur installable qui porpose directement tout ça et il faut le dévellopper. Le développement peut être basé sur xulrunner-2.0 ou sur webkit en gtk ou qt.

Pour faire une démo de l'installation je suis allez au plus simple même si il ne répond pas à tous les besoin en me basant sur le programme de démo GTkLauncher de webkit. Pour le faire fonctionner on aura besoin de libwebkit-1.0-2. Donc

# apt-get install libwebkit-1.0-2

En principe la compilation du programme doit ce faire sur une autre machine et on a besoin des paquets suivants

# apt-get install build-essential libwebkit-dev

et du code source de GtkLauncher:

/*
 * Copyright (C) 2006, 2007 Apple Inc.
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Modification pour la démo:
 *  - ajout d'un bouton fermeture
 *  - ajout du proxy
 *  - force la taille de la fenêtre à 1024x768 non redimentionable. 
 *    Cette partie ne devrait pas être en dur mais passer en argument pour 
 *    s'adapter aux dimensions de l'écran.
 */
 
#include <gtk/gtk.h>
#include <webkit/webkit.h>
 
static gint windowCount = 0;
 
static GtkWidget* createWindow(WebKitWebView** outWebView);
 
static void activateUriEntryCb(GtkWidget* entry, gpointer data)
{
    WebKitWebView *webView = g_object_get_data(G_OBJECT(entry), "web-view");
    const gchar* uri = gtk_entry_get_text(GTK_ENTRY(entry));
    g_assert(uri);
    webkit_web_view_load_uri(webView, uri);
}
 
static void updateTitle(GtkWindow* window, WebKitWebView* webView)
{
    GString *string = g_string_new(webkit_web_view_get_title(webView));
    gdouble loadProgress = webkit_web_view_get_progress(webView) * 100;
    g_string_append(string, " - WebKit Launcher");
    if (loadProgress < 100)
        g_string_append_printf(string, " (%f%%)", loadProgress);
    gchar *title = g_string_free(string, FALSE);
    gtk_window_set_title(window, title);
    g_free(title);
}
 
static void linkHoverCb(WebKitWebView* page, const gchar* title, const gchar* link, GtkStatusbar* statusbar)
{
    guint statusContextId =
      GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(statusbar), "link-hover-context"));
    /* underflow is allowed */
    gtk_statusbar_pop(statusbar, statusContextId);
    if (link)
        gtk_statusbar_push(statusbar, statusContextId, link);
}
 
static void notifyTitleCb(WebKitWebView* webView, GParamSpec* pspec, GtkWidget* window)
{
    updateTitle(GTK_WINDOW(window), webView);
}
 
static void notifyLoadStatusCb(WebKitWebView* webView, GParamSpec* pspec, GtkWidget* uriEntry)
{
    if (webkit_web_view_get_load_status(webView) == WEBKIT_LOAD_COMMITTED) {
        WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
        const gchar *uri = webkit_web_frame_get_uri(frame);
        if (uri)
            gtk_entry_set_text(GTK_ENTRY(uriEntry), uri);
    }
}
 
static void notifyProgressCb(WebKitWebView* webView, GParamSpec* pspec, GtkWidget* window)
{
    updateTitle(GTK_WINDOW(window), webView);
}
 
static void destroyCb(GtkWidget* widget, GtkWidget* window)
{
    if (g_atomic_int_dec_and_test(&windowCount))
      gtk_main_quit();
}
 
static void closeCb(GtkWidget* widget,  WebKitWebView* webView)
{
    gtk_main_quit();
}
 
static void goBackCb(GtkWidget* widget,  WebKitWebView* webView)
{
    webkit_web_view_go_back(webView);
}
 
static void goForwardCb(GtkWidget* widget, WebKitWebView* webView)
{
    webkit_web_view_go_forward(webView);
}
 
static WebKitWebView*
createWebViewCb(WebKitWebView* webView, WebKitWebFrame* web_frame, GtkWidget* window)
{
    WebKitWebView *newWebView;
    createWindow(&newWebView);
    return newWebView;
}
 
static gboolean webViewReadyCb(WebKitWebView* webView, GtkWidget* window)
{
    gtk_widget_grab_focus(GTK_WIDGET(webView));
    gtk_widget_show_all(window);
    return FALSE;
}
 
static gboolean closeWebViewCb(WebKitWebView* webView, GtkWidget* window)
{
    gtk_widget_destroy(window);
    return TRUE;
}
 
static useProxy(void)
{  
    SoupSession* session = webkit_get_default_session();
    if(session) {
       SoupURI *uri = soup_uri_new("http://127.0.0.1:3128");
       if(uri) {
          g_object_set(session, "proxy-uri", uri, NULL);
          soup_uri_free(uri);
       }
    }
}
 
static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidget* statusbar, WebKitWebView* webView)
{
    GtkWidget *scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
    gtk_container_add(GTK_CONTAINER(scrolledWindow), GTK_WIDGET(webView));
 
    g_signal_connect(webView, "notify::title", G_CALLBACK(notifyTitleCb), window);
    g_signal_connect(webView, "notify::load-status", G_CALLBACK(notifyLoadStatusCb), uriEntry);
    g_signal_connect(webView, "notify::progress", G_CALLBACK(notifyProgressCb), window);
    g_signal_connect(webView, "hovering-over-link", G_CALLBACK(linkHoverCb), statusbar);
    g_signal_connect(webView, "create-web-view", G_CALLBACK(createWebViewCb), window);
    g_signal_connect(webView, "web-view-ready", G_CALLBACK(webViewReadyCb), window);
    g_signal_connect(webView, "close-web-view", G_CALLBACK(closeWebViewCb), window);
 
    useProxy();
 
    return scrolledWindow;
}
 
static GtkWidget* createStatusbar()
{
    GtkStatusbar *statusbar = GTK_STATUSBAR(gtk_statusbar_new());
    guint statusContextId = gtk_statusbar_get_context_id(statusbar, "Link Hover");
    g_object_set_data(G_OBJECT(statusbar), "link-hover-context",
        GUINT_TO_POINTER(statusContextId));
 
    return GTK_WIDGET(statusbar);
}
 
static GtkWidget* createToolbar(GtkWidget* uriEntry, WebKitWebView* webView)
{
    GtkWidget *toolbar = gtk_toolbar_new();
 
#if GTK_CHECK_VERSION(2, 15, 0)
    gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
#else
    gtk_toolbar_set_orientation(GTK_TOOLBAR(toolbar), GTK_ORIENTATION_HORIZONTAL);
#endif
    gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
 
    GtkToolItem *item;
 
    /* the back button */
    item = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
    g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(goBackCb), webView);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
 
    /* The forward button */
    item = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
    g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(goForwardCb), webView);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
 
    /* The URL entry */
    item = gtk_tool_item_new();
    gtk_tool_item_set_expand(item, TRUE);
    gtk_container_add(GTK_CONTAINER(item), uriEntry);
    g_signal_connect(G_OBJECT(uriEntry), "activate", G_CALLBACK(activateUriEntryCb), NULL);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
 
    /* The go button */
    g_object_set_data(G_OBJECT(uriEntry), "web-view", webView);
    item = gtk_tool_button_new_from_stock(GTK_STOCK_OK);
    g_signal_connect_swapped(G_OBJECT(item), "clicked", G_CALLBACK(activateUriEntryCb), (gpointer)uriEntry);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
 
    item = gtk_tool_button_new_from_stock(GTK_STOCK_CLOSE);
    g_signal_connect_swapped(G_OBJECT(item), "clicked", G_CALLBACK(closeCb), (gpointer)uriEntry);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
 
    return toolbar;
}
 
static GtkWidget* createWindow(WebKitWebView** outWebView)
{
    WebKitWebView *webView;
    GtkWidget *vbox;
    GtkWidget *window;
    GtkWidget *uriEntry;
    GtkWidget *statusbar;
 
    g_atomic_int_inc(&windowCount);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 1024, 768);
    gtk_widget_set_size_request(window, 1024, 768);
    gtk_widget_set_name(window, "GtkLauncher");
 
    webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    uriEntry = gtk_entry_new();
 
    vbox = gtk_vbox_new(FALSE, 0);
    statusbar = createStatusbar(webView);
    gtk_box_pack_start(GTK_BOX(vbox), createToolbar(uriEntry, webView), FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), createBrowser(window, uriEntry, statusbar, webView), TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
 
    gtk_container_add(GTK_CONTAINER(window), vbox);
 
    g_signal_connect(window, "destroy", G_CALLBACK(destroyCb), NULL);
 
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
 
    if (outWebView)
        *outWebView = webView;
 
    return window;
}
 
static gchar* filenameToURL(const char* filename)
{
    if (!g_file_test(filename, G_FILE_TEST_EXISTS))
        return 0;
 
    GFile *gfile = g_file_new_for_path(filename);
    gchar *fileURL = g_file_get_uri(gfile);
    g_object_unref(gfile);
 
    return fileURL;
}
 
#ifndef GTK_API_VERSION_2
static void disablePlugin(const char* pluginName)
{
    WebKitWebPluginDatabase *database = webkit_get_web_plugin_database();
    GSList *plugins = webkit_web_plugin_database_get_plugins(database);
    GSList *p;
 
    for (p = plugins; p; p = g_slist_next(p)) {
        WebKitWebPlugin *plugin = WEBKIT_WEB_PLUGIN(p->data);
 
        if (!g_strcmp0(webkit_web_plugin_get_name(plugin), pluginName))
            webkit_web_plugin_set_enabled(plugin, FALSE);
    }
 
    webkit_web_plugin_database_plugins_list_free(plugins);
}
#endif
int main(int argc, char* argv[])
{
    WebKitWebView *webView;
    GtkWidget *main_window;
 
    gtk_init(&argc, &argv);
    if (!g_thread_supported())
        g_thread_init(NULL);
 
#ifndef GTK_API_VERSION_2
    disablePlugin("Shockwave Flash");
#endif
 
    main_window = createWindow(&webView);
 
    gchar *uri =(gchar*)(argc > 1 ? argv[1] : "http://www.google.com/");
    gchar *fileURL = filenameToURL(uri);
 
    webkit_web_view_load_uri(webView, fileURL ? fileURL : uri);
    g_free(fileURL);
 
    gtk_widget_grab_focus(GTK_WIDGET(webView));
    gtk_widget_show_all(main_window);
    gtk_main();
 
    return 0;
}

et du Makefile

all: GtkLauncher
 
GtkLauncher: main.c
	gcc -DGTK_API_VERSION_2 -o GtkLauncher main.c `pkg-config --cflags --libs webkit-1.0` 
 
 
install: GtkLauncher
	install GtkLauncher /opt/
 
clean:
	rm -f GtkLauncher

que l'on installe avec la commande

# make install
configuration de la session

On configure nodm pour se connecter directement sur le compte linuxquimper en éditant le fichier /etc/default/nodm

# nodm configuration

# Set NODM_ENABLED to something different than 'false' to enable nodm
NODM_ENABLED=true

# User to autologin for
NODM_USER=linuxquimper

# xinit program
NODM_XINIT=/usr/local/bin/xinit

# First vt to try when looking for free VTs
NODM_FIRST_VT=7

# X session
NODM_XSESSION=/etc/X11/Xsession

# Options for the X server
NODM_X_OPTIONS='vt7 -nolisten tcp'

# If an X session will run for less than this time in seconds, nodm will wait an
# increasing bit of time before restarting the session.
NODM_MIN_SESSION_TIME=120

On créer le fichier /usr/local/bin/xinit que l'on rend exécutable:

#!/bin/sh
 
rsync -a --delete /opt/linuxquimper /home/
 
exec /usr/bin/xinit "$@"

et on créer le ficher /etc/X11/Xsession.d/98_linuxquimper pour lancer la session. ON ne peut pas utiliser de fichier $HOME/.xsession car on va passer la partition /home en noexec.

# This file is sourced by Xsession(5), not executed.
 
if [ "$USER" = "linuxquimper" ] ; then
 
  export LANG=fr_FR.UTF-8
  // exec xulrunner-2.0 /opt/conkeror/application.ini
  exec /opt/GtkLauncher
 
  # Reset default startup
  STARTUP=/bin/false
fi
 
# vim:set ai et sts=2 sw=2 tw=80:

Puis on peut lancer la session utilisateur avec /etc/init.d/nodm start.

fin de la configuration

Il faut sécuriser l'accés au shell grub en lui métant un mot de passe. On option un mot de passe chiffré pour grub avec la commande grub-mkpasswd-pbkdf2. on recupére le résultat de cette commande que l'on met dans un fichier /etc/grub/01_password que l'on rend éxécutable:

#!/bin/sh
set -e
 
cat <<EOF
 
set superusers="root"
password_pbkdf2 root grub.pbkdf2.sha512.64.2D0F37B9.37B35EF82745CEA0B146C451BD90BDC12DAB53EF29919FA888C7FA5E6417EBD0072FF9D0DC917D69E68046ECA991C799687849A1D012B2057AE82E9A2688DA83
 
EOF

Pour avoir un boot graphique on peut installer plymouth et ajouter splash à la ligne de commande linux

# apt-get install plymouth plymouth-themes-solar

et on édite le fichier /etc/default/grub

# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.

GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
GRUB_DISABLE_LINUX_RECOVERY="true"

# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"

ensuite on peut mettre le fichier grub.cfg à jour

# update-grub

on termine on mettant toutes les partions sauf / en noexec et / en read-only dans le fichier /etc/fstab

# /etc/fstab: static file system information.
#
# Use 'blkid -o value -s UUID' to print the universally unique identifier
# for a device; this may be used with UUID= as a more robust way to name
# devices that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    nodev,noexec,nosuid 0       0
UUID=d240c895-f500-42fb-b34a-1335cf861c1b /               ext4    errors=remount-ro,ro 0       1
UUID=0ffae1e9-f09a-4aa5-a8d0-7a681304e8d9 none	swap	sw	 0       0
UUID=cb7b0fac-b92c-4c8c-9792-5a2ea4e1032b /home           ext4	defaults,noexec	0       2
UUID=5fe5af3f-f3a8-479e-bd43-e8a77f2df74b /data           ext4	defaults,noexec	0       2

/data/log /var/log none bind 0 0
/data/squid /var/spool/squid none bind 0 0

tmpfs           /tmp            tmpfs   defaults,noexec        0       0
tmpfs           /var/tmp        tmpfs   defaults,noexec        0       0
tmpfs           /var/run        tmpfs   defaults,noexec        0       0

## Pas de device externe
#/dev/fd0        /media/floppy0  auto    rw,user,noauto,noexec,utf8 0       0

Aprés on peut rebooter la machine pour voir si tout fonctionne.

1)
le web n'est pas Internet
2)
en principe 3 devrait suffire si on externalise le proxy et les logs
3)
ou pulseaudio
papweb.1308558482.txt.gz · Dernière modification: 2023/07/18 23:11 (modification externe)