Journal Mon serveur Web

Posté par  .
Étiquettes :
0
6
juin
2007
Je cherchais un serveur web simple sous debian : fournir une page de texte, quelle que soit la requête.
Apparemment trop simple, j'ai du le faire moi même.

Les requêtes HTTP depuis des adresses blacklistées par mon firewall sont redirigées vers un port interne, pris en charge par inetd.

Si il y en a que cela intéresse, voici le code :

Un exemple de redirection iptables :
iptables -t nat -A PREROUTING -s 221.232.0.0/14 -p tcp --dport www -j REDIRECT --to-port 1090


La ligne dans inetd :
1090 stream tcp nowait nobody /usr/bin/opws.sh opws.sh


Le fichier /usr/bin/opws.sh :
1 #!/bin/sh
2
3 HTML_FILE=/var/www/blacklisted/index.html
4 ANSWER='HTTP/1.1 403 Forbidden'
5 SERVER=Apache
6
7 DATE=`/bin/date -u -R | /bin/sed 's/+0000/GMT/'`
8 LENGTH=`/bin/ls -l $HTML_FILE | awk '{ print $5 }'`
9
10 echo $ANSWER
11 echo Date : $DATE
12 echo Server : $SERVER
13 echo Content-Type : text/HTML
14 echo Content-Length : $LENGTH
15
16 # blank line to separate header form content
17 echo
18
19 # start to send content
20 /bin/cat $HTML_FILE


Quant au fichier /var/www/blacklisted/index.html, mettez ce que vous voulez...

Il ne me manque plus qu'à rajouter des entrées dans syslog...

Les commentaires sont les bienvenus, il y a certainement des failles ?
  • # Racisme ?

    Posté par  . Évalué à 2.

    Tu n'aimes pas les chinois ?
    • [^] # Re: Racisme ?

      Posté par  . Évalué à 5.

      Trés drôle, et je m'y attendais...

      Je reconnais que je casse l'universalité du web, mais le peu de sites que j'héberge sont en français, et n'ont aucun intérêt pour les chinois, les pakistanais, les japonais, les coréens, etc...

      Sil il y a des français expatriés, cette redirection les informe que le réseau qu'ils utilisent a été temporairement blacklisté, et qu'ils peuvent utiliser un proxy, voire m'envoyer un mel.

      C'est fatiguant à force, les remplissage de logs apache ou sshd, invalid request, invalid user, etc...
      Quand on épluche ses logs assez souvent, cela devient difficile de discerner une attaque réelle au milieu de cette inondation de requêtes invalides venue de vers et autres saletés qui inondent ces réseaux.

      Couplé à fail2ban, cela me permet de passer moins de temps a lire mes logs, et de me concentrer sur d'autres projets.

      C'est plus constructifs que de jouer au chat et a la souris avec des pirates en herbes en train de tester si j'ai bien mis à jour PhpBB ou si j'utilise phpmyadmin...

      Vivement ipv6.

      Je retourne programmer...
      • [^] # Re: Racisme ?

        Posté par  . Évalué à 2.

        Pourquoi vivement ipv6 ? y'aura plus de robots chinois etc ?
        • [^] # Re: Racisme ?

          Posté par  . Évalué à 3.

          parce que scanner un range ipv4 pour trouver des hosts défaillants et autres, et faire la meme chose en ipv6, ben c'est pas du tout le meme boulot :D
  • # Pourquoi répondre ?

    Posté par  . Évalué à 6.

    Pourquoi répondre une erreur 403 Forbidden si c'est pour une adresse blacklistée ?
    iptables -t nat -A PREROUTING -s 221.232.0.0/14 -p tcp --dport www -j DROP
    n'irait pas ?

    Un petit bout de code C serait plus approprié à mon gout, sans inetd.
    But : éviter de créer plein de processus à chaque requête et de faciliter un DOS (sh, `date ..` , `ls ... ` , /bin/cat --> 4 processus)
    si je ne me trompe pas ?
    • [^] # Re: Pourquoi répondre ?

      Posté par  . Évalué à 2.

      Pourquoi répondre une erreur 403 Forbidden si c'est pour une adresse blacklistée ?
      Je réponds plus Haut.

      Je n'ai pas de compilateur C sur mon serveur, mais si quelqu'un connaît un serveur web qui fasse cela, je suis preneur.
    • [^] # Re: Pourquoi répondre ?

      Posté par  (Mastodon) . Évalué à 4.

      Je le ferais plutôt comme ça :

      iptables -t nat -A PREROUTING -s 221.232.0.0/14 -p tcp --dport www -j REJECT --reject-with icmp-port-unreachable

      Si les paquets sont juste jetés, ils peuvent insister.
      Si la réponse est immédiate et dit « ce port n'est pas ouvert » c'est simple et clair, inutile d'aller chercher plus loin.
      Utile en cas de nmap sur ta machine pour chercher les failles, et les points d'accès, là c'est simple, c'est fermé, alors que si tu droppes simplement, il y a un doute.

      Je me trompe peut-être, je ne suis pas expert en sécurité, loin de là, mais voilà,

      Yth.
      • [^] # Re: Pourquoi répondre ?

        Posté par  (site web personnel) . Évalué à 2.

        Une variante consiste à utiliser la target TARPIT d'iptables. Elle permet de faire trainer le plus longtemps possible la session TCP. En pratique, c'est souvent utiliser contre les vers.
  • # Optimisations:

    Posté par  (site web personnel) . Évalué à 6.

    pour les raisons évoquées plus haut, j'optimiserai le
    script de la sorte (limite les appels à 2 forks):


    1 #!/bin/sh
    2
    3 DATA=`cat /var/www/blacklisted/index.html`
    4 ANSWER='HTTP/1.1 403 Forbidden'
    5 SERVER=Apache
    6
    7 DATE=`LANG=C /bin/date -u +"%a, %d %b %Y %H:%M:%S GMT"`
    8 LENGTH=${#DATA}
    9
    10 echo $ANSWER
    11 echo Date : $DATE
    12 echo Server : $SERVER
    13 echo Content-Type : text/HTML
    14 echo Content-Length : $LENGTH
    15
    16 # blank line to separate header form content
    17 echo
    18
    19 # start to send content
    20 echo $DATA
    • [^] # Re: Optimisations:

      Posté par  . Évalué à 10.

      On peut même se passer du content-length en HTTP/1.0, vu que pas de keep-alived. (Sans keep-alived, la fin du document c'est quand la connexion est fermée).

      Sinon en PHP, 0 fork:


      #!/usr/bin/php5
      HTTP/1.0 403 Forbidden
      Date: <?php echo date(DATE_RFC822)."\r\n"; ?>
      Server: Apache
      Content-Type: text/html

      <?php readfile('/var/www/blacklisted/index.html'); ?>


      Ou en C:

      #include <time.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <errno.h>

      #define STATUS "HTTP/1.0 403 Forbidden"
      #define SERVER "Apache"
      #define CONTENT_TYPE "text/html"

      #define PAGE_FILE "/var/www/blacklisted/index.html"

      int main(int argc, char *argv[])
      {
      char date[50];
      time_t t;
      struct tm *tmp;
      FILE *fp;
      char line[1024];

      t = time(NULL);
      tmp = localtime(&t);
      strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", tmp);

      printf("%s\r\n", STATUS);
      printf("Date: %s\r\n", date);
      printf("Server: %s\r\n", SERVER);
      printf("Content-Type: %s\r\n", CONTENT_TYPE);
      printf("\r\n");

      if ((fp = fopen(PAGE_FILE, "r")) == NULL) {
      perror("Could not read file");
      return 1;
      }

      while (fgets(line, 1024, fp) != NULL) {
      printf("%s", line);
      }

      fclose(fp);

      return 0;
      }
      • [^] # Re: Optimisations:

        Posté par  . Évalué à 1.

        Bien sûr, la solution en PHP est intéressante, mais je préfère de loin la solution en C.
        Offrir PHP à des adresses blacklistées, n'est-ce pas imprudent ?

        Il me semble qu'en PHP nous perdons tout l'intérêt du programme sensé écarter les crackers.

        La simple ligne #!/usr/bin/php5 exécute certainement beaucoup de code, analyse POST, GET, initialisations, etc... ouvrant ainsi la porte à autant de failles potentielles.
        • [^] # Re: Optimisations:

          Posté par  . Évalué à 3.

          Et pourquoi pas un simple cat nom_du_fichier.txt (avec les headers et le code html) ? (j'ai l'impression d'avoir rater quelque chose :) )
        • [^] # Re: Optimisations:

          Posté par  (site web personnel) . Évalué à 4.

          Euh, je ne pense pas que le script php analyse quoi que ce soit dans les entêtes. Ce n'est pas du CGI là, simplement un script qui balance du contenue sur sa sortie, et qui a priori doit recevoir les en-têtes sur son entrée. L'entrée pourrait contenir n'importe quoi, c'est dans ce contexte précis que c'est des en-têtes HTTP.
          Mais bon, je rejoins ce qui a été dit plus haut : autant mettre les en-têtes avec le contenu de la page dans un fichier, et le balancer.
          • [^] # Re: Optimisations:

            Posté par  . Évalué à 2.

            Il faut forcément un programme pour le balancer, le fichier ;)

            Mais je crois que l'entête Date est obligatoire, et elle ne peut pas être mise en dur dans le fichier (en fait ça marche très bien sans cette entête du moment qu'on envois pas de cookies/expires, etc...)
            • [^] # Re: Optimisations:

              Posté par  . Évalué à 6.

              > Mais je crois que l'entête Date est obligatoire
              Pas vraiment, car la RFC2616 autorise les serveurs non datés:

              14.18 Date

              [...]

              Origin servers MUST include a Date header field in all responses, except in these cases:

              [...]

              3. If the server does not have a clock that can provide a
              reasonable approximation of the current time, its responses
              MUST NOT include a Date header field. In this case, the rules
              in section 14.18.1 MUST be followed.

              [...]

              14.18.1 Clockless Origin Server Operation

              Some origin server implementations might not have a clock available. An origin server without a clock MUST NOT assign Expires or Last- Modified values to a response, unless these values were associated with the resource by a system or user with a reliable clock. It MAY assign an Expires value that is known, at or before server configuration time, to be in the past (this allows "pre-expiration" of responses without storing separate Expires values for each resource).

              (voir http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14(...)
              • [^] # Re: Optimisations:

                Posté par  . Évalué à 2.

                Merci de tous ses commentaires, et dommage que je ne puisse les plusser qu'une fois chacun.
                Je sais maintenant que je peux utiliser un simple fichier texte.

                Je n'utilise pas de redirections apache pour des raisons de sécurité et de performances.
            • [^] # Re: Optimisations:

              Posté par  (site web personnel) . Évalué à 5.

              Certes, mais ce programme existe déjà, et il se nomme cat ;).
              • [^] # Re: Optimisations:

                Posté par  . Évalué à 3.

                ca me rassures de voir qu'une personne pense aussi comme moi (voir mon commentaire sans reponses au dessus).
  • # montée en charge ?

    Posté par  . Évalué à 2.

    dans le même genre je me demande comment iptables va se comporter si on n'a pas 1 mais 50 ou 100 ou plus blocs d'ips qu'on décide de filtrer gaiement

    exemple de listes de blocs d'ip ici :

    http://blackholes.us/zones/countries/

    (parce que après l'asie c'est l'amérique du sud qui commence à bien s'équiper et à être vérolé en permanence)
  • # Redirect Apache

    Posté par  (site web personnel) . Évalué à 1.

    Si tu as déjà un serveur apache pourquoi ne pas utiliser mod_rewrite ?
    (Quoique c'est peut-être un peu lourd)
    • [^] # Re: Redirect Apache

      Posté par  . Évalué à 2.

      ben dans les faits il se passe beaucoup de choses, et par exemple j'ai vu plusieurs fois passer ceci :

      131.211.183.51 - - [04/Jun/2007:19:12:49 +0200] "GET /phpmyadmin/main.php HTTP/1.0" 404 293
      (660 variantes)
      131.211.183.51 - - [04/Jun/2007:19:13:28 +0200] "GET /administrator/phpMyAdmin-2.8.3/main.php HTTP/1.0" 404 293

      669 en donc moins de 40 secondes, soit plus de 15 à la seconde

      répondre vite et bien (un gentil 404, tout de suite) à ce genre de recherches de vulnérabilité n'est pas une bonne idée.

      alors entre faire un drop/reject ou ajouter un sleep(10) dans son 404 parce qu'on sait que l'outil en face lance une requete à la fois, peu importe du moment que ça marche et que le site reste utilisable pour les autres usagers
  • # Apache ?

    Posté par  . Évalué à 4.

    Je ne comprends pas pourquoi tu ne fais pas traiter ces requêtes par Apache ?

    Tu fais écouter Apache sur le port 1090, port sur lequel tu déclares un VirtualHost qui ne contient qu'un document: ta page d'erreur. Non testé:

    Listen 1090
    
    <VirtualHost *:1090>
            DocumentRoot /var/www/blacklisted/
            ServerName host.foo.com
            ErrorLog /dev/null
            CustomLog /dev/null NullFormat
    
            ErrorDocument   403     /index.html
    
            <Directory "/var/www/blacklisted/">
                    Options None
                    DirectoryIndex index.html
                    AllowOverride None
                    Order Deny,Allow
                    Deny from All
            </Directory>
    
    </VirtualHost> 
    

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.