OpCode.eu.org

Blog O autorze O serwisie
2021-12-05

Proste przydatne narzędzia i kawałki kodu

Wpis zbiera proste narzędzia, które mogą okazać się przydatne w różnych zastosowaniach.

Serwer SMTP w busybox (netcat, sh, awk)

Jest to bardzo prosty serwer SMTP (wykorzystujący do nasłuchu netcat'a). Umożliwia on sterowanie (wykonywanie zdalnych poleceń przy pomocy odpowiednio spreparowanych maili)

Pozwala na odbieranie poczty i wykorzystywanie jej do sterowania systemem na którym nie mamy serwera pocztowego, a dysponujemy jedynie podstawowymi narzędziami - w teorii powinien wystarczyć busybox.

Uruchomienie: while true; do netcat -l -p 25 -e smtp.sh; done. Wymaga busybox z netcatem potrafiącym odpalić skrypt w -e lub innego netcata mającego taką funkcjonalność..

Kod źródłowy (do pobrania):

#!/bin/bash

DOMAIN="example.org"

IS_DATA=false; SENDER=""; RECEIVER="";
echo "220 $DOMAIN SMTP server by RRP `date -R`"

while read line; do
    echo "Q (data=$IS_DATA): Y $line" >> /tmp/smtp-log.txt

    if $IS_DATA; then
        if echo "$line" | tr -d '\r' | awk '$0=="." {exit 0;} {exit 1}'; then
            IS_DATA=false
            echo -en "250 OK\r\n"
            continue
        fi

        ##########################
        # WŁAŚCIWA TREŚĆ SKRYPTU #
        ##########################
        # jest to powtarzane dla każdej linii przesyłanej jako treść maila (łącznie z nagłówkami)
        # możemy sprawdzać nadawcę kopertowego: "$SENDER"
        # możemy sprawdzać adresata kopertowego: "$RECEIVER"
        # możemy sprawdzać aktualną linię z maila: "$line" tak jak to pokazano poniżej:

        echo "$line" | tr -d '\r' | awk '
            $1=="action" {
                cmd=sprintf("make_action.sh %s %s", $2, $3);
            }
            $1=="stop" {
                cmd=sprintf("killall .... ");
            }
            END {
                system(cmd);
            }
        ' > /dev/null 2> /dev/null &
        # UWAGA: musi to być wyciszone i przechodzić w tło

    else
        echo "$line" | tr -d '\r' | awk -v DOMAIN="$DOMAIN" '
        BEGIN {
            IGNORECASE=1
            FS="[ :\t]+"
        }
        $1 ~ "^(HE)|(EH)LO$" {
            printf("250 %s Hello %s, pleased to meet you\r\n", DOMAIN, $2);
            system( sprintf("echo \"R: 250 %s Hello %s, pleased to meet you\" >> /tmp/smtp-log.txt", DOMAIN, $2) );
            exit 0;
        }
        $1 ~ "^MAIL$" && $2 ~ "^FROM$" && $3 != "" {
            printf("250 OK\r\n");
            system( sprintf("echo \"R: 250 OK\" >> /tmp/smtp-log.txt") );
            exit 1;
        }
        $1 ~ "^RCPT$" && $2 ~ "^TO$" && $3 != "" {
            printf("250 OK\r\n");
            system( sprintf("echo \"R: 250 OK\" >> /tmp/smtp-log.txt") );
            exit 2;
        }
        $1 ~ "^DATA$" {
            printf("354 Enter message, ending with \".\" on a line by itself\r\n");
            system( sprintf("echo \"R: 354 Enter message, ending with \".\" on a line by itself\" >> /tmp/smtp-log.txt") );
            exit 3;
        }
        $1 ~ "^QUIT$" {
            printf("221 %s closing connection\r\n", DOMAIN);
            system( sprintf("echo \"R: 221 %s closing connection\" >> /tmp/smtp-log.txt", DOMAIN) );
            exit 4;
        }
        {
            printf("500 unrecognized command\r\n");
            system( sprintf("echo \"R: 500 unrecognized command (%s)\" >> /tmp/smtp-log.txt", $1) );
            exit 0;
        }
        '
        case $? in
            1) SENDER=`echo $line | tr -d '\r' | awk 'BEGIN {FS="[ :\t<>]+"} {print $3}'` ;;
            2) RECEIVER=`echo $line | tr -d '\r' | awk 'BEGIN {FS="[ :\t<>]+"} {print $3}'` ;;
            3) IS_DATA=true ;;
            4) exit ;;
        esac
    fi
done;

Serwer HTTP w pythonie

Jest to prosty serwer HTTP z użyciem Pythona i jego standardowego modułu http.server. Serwer ten (w odróżnieniu od wywołania typu python3 -m http.server pozwalającego serwować zawartość katalogów) pozwala na wykonanie dowolnej akcji w odpowiedzi na żądanie HTTP i przesłanie dowolnej odpowiedzi do klienta. Może być użyty np. do zdalnego sterowania poprzez HTTP.

Kod źródłowy (do pobrania):

#!/usr/bin/env python3

from http.server import HTTPServer, BaseHTTPRequestHandler

class HttpHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain;charset=utf-8')
        self.end_headers()
        # tu możemy wykonać jakąś akcję
        # (w oparciu o argumenty żądania GET zawarte w self.path)
        # i odesłać odpowiedź:
        self.wfile.write(('Hello, world!\nŻądanie:' + self.path).encode())

httpd = HTTPServer(('localhost', 8000), HttpHandler)
httpd.serve_forever()
Tagi: shell python network