scripting / openVPN / emailNotification /
-
Also eine Textdatei erzeugen, die du auslesen kannst im Skript ist ja mit dem "Filer" Package kein Problem und durch das Paket bleibt die Datei auch nach einem Update da und hat den gewünschten Inhalt. Auch das Skript kannst du so auf der Sense irgendwo sinnvoll ablegen und sicherstellen, dass es mit korrektem Inhalt und Rechten dann auch nach Updates wieder da ist. Eine Abfrage mit Skripting in diese User-Datei rein ist dann nicht soo schwer, oder verstehe ich deine Idee hier falsch?
-
-
txt datei erzeugen mit filer ! Danke f hinweis kannte das Paket nicht
(wird in Angriff genommen) -
verstehe ich es richtig das ich das script und die Berechtigungen auch über filer machen sollte weil sonst nach update alles anders (sein könnte)
-
ja alles richtig verstanden
-
und jaaaaaa es ist soooo schwer (für mich) ich krieg das mit der if und der for each der txt nicht hin (denn ich hätte das gerne / ich will es auch so bauen, weil ich stur bin und es sicher geht) das das ganze script im openVPN server advanced aufgerufen wird.
die umschachtelungen für einen Time Report machen wir in einer anderen baustelle. (von der hab ich mit multiWAN gerade eine richtige ausgefasst)
ich freu mich auf comment / feedback / hilfe
lgNp -
-
@noplan said in scripting / openVPN / emailNotification /:
verstehe ich es richtig das ich das script und die Berechtigungen auch über filer machen sollte weil sonst nach update alles anders (sein könnte)
Wenn du willst, dass das Skript und die Berechtigungen nach einem Update noch da sind - ja, dann solltest du das auch in Filer packen. Bei einem simplen Update könnte es sein dass es noch da ist wenn dus in das richtige Verzeichnis gepackt hast (eines das vom Update nicht betroffen ist), aber bei einer Neuinstallation wäre es sonst weg. So ist es durch Filer und das Konfig-Backup in der Sicherung mit drin :)
ja alles richtig verstanden
OK Recap:
- Du hast einen Scriptcall im OVPN Server drin via client-disconnect. Erstmal ja nichts Schlechtes. Das ruft das Skript auf (würde ich nciht unbedingt nach /root packen aber seis drum, ist da erstmal egal).
- Ist der Skriptoutput mit den paar Zeilen PHP wirklich der komplette Inhalt von disconnect.sh? Wenn ja, sollte man vielleicht das .sh überdenken, denn ein Shell Skript per se ist es nicht, eher ein PHP Skript. Aber seis drum, ich fände es nur irritierend
- Du willst jetzt aus diesem PHP Skript quasi das Logging so steuern, dass die 3 Zeilen nach dem Require nur dann ausgeführt werden, wenn der "common_name" in einer Liste von Usern steht die du pflegst? Ist das richtig?
Edit: Oh lese gerade was von Gruppen. Wie soll denn die Gruppenzugehörigkeit unterschieden werden? OpenVPN kennt ja deine Gruppen nicht, also könntest du m.E. nur auf den Usernamen gehen, nicht auf Gruppen?
Gruß Jens
-
ob der common_name es steuert oder die IP Adresse die dem common_name mittels CSO zugewiesen wird ist egal was einfacher ist, ich dachte an IP
Ja war mit klar mit der einzigen Unterscheidungsmöglichkeit
common_name oder IP Adresse
die Gruppen sind einfache txt Dateien die man mit entweder dem common_name oder der IP befüllt ... eine andere Befüllung zB aus einem Alias wird kompliziert aber vielleicht cooler.ja ich bin voll bei dir (speicherort, .sh,)
ja das script soll nur dann ausgeführt werden
wenn die IP oder der common_Name in der Datei gefunden wird
ich bevorzug ja noch immer die IP denn wenn das CSO nicht funktionier, verbindet er (der Client zwar) aber kann aufgrund der Regeln nix machen.
das siehst dann eh im LOG.je mehr man darüber nachdenkt desto mehr denk ich mir das kann j anicht so schwer hinzubekommen sein.
lgNP
-
Also IP wäre IMHO recht einfach machbar, wenn dus geschickt machst, könntest du dann sogar auf die Datei zum Auslesen verzichten, müsstest dann nur die PHP Datei etwas aufbohren.
Bspw. nur so dahin gesponnen:
wenn du alle IPs, die du Loggen willst erst ab - sagen wir - .128-.254 vergibst und alles darunter sind dann Einwahlbereiche, die du per Radius oder CSOs vergibst, die du nicht loggen willst, dann kannst du selbst es steuern via CSO, wer geloggt wird oder nicht (und die entsprechenden IPs oder Bereiche gleich noch mit einem Alias auf der pfSense einfangen und ggf. andere Regeln auf dem OVPN Interface vergeben).
Weitergesponnen:
- Aufteilung in theoretische CIDR Blöcke mit bspw. 32 IPs oder 64 IPs
- Dann Vergabe via CSOs ab CIDR Boundary also bspw. ab .129+ o.ä.
- Keine CSO? OVPN vergibt IP selbst aus den untersten IP Bereichen, Client bekommt .2, .3, .4 etc und wird nicht geloggt (bspw. Admins/Mitarbeiter)
- CSO für Fremdfirmen und Drittanbieter, werden über CSO auf fixe IP gesetzt (.129, .130, .131...) und dadurch im Skript automatisch geloggt
Das ist wie gesagt nur jetzt so mal dahin gesponnen aber problemlos möglich, da du im Skript vor dem IF case
... $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a'); ...
den Client mit IP kennst -
getenv(ifconfig_pool_remote_ip)
. Bei einem VPN Netz von 10.0.8.0/24 z.B. könnte man das so quick & dirty bauen:$client_ip=getenv(ifconfig_pool_remote_ip); $min_ip="10.0.8.129"; $max_ip="10.0.8.254"; if (ip2long($min_ip) < ip2long($client_ip) && ip2long($client_ip) < ip2long($max_ip)) { // hier den Code der nur dann ausgeführt werden soll, also dein $local_connect und der disconnect part } // kein else nötig, aber wenn du noch was machen willst wenn es eine IP außerhalb des Ranges ist, dann kann man das hier mit einem "} else {" Case anbauen
Das prüft einfach nur durch IP-in-numerischen-Long-Wert umrechnen, ob die Client IP zwischen den beiden Boundaries liegt und wenn ja -> Go!
Damit kannst du den Bereich problemlos im Skript definieren und wer geloggt wird entscheidet sich wie gesagt durch deine CSO-IP-Vergabe :)
Grüße
-
ich bin jetzt überfordert ;)
liegt aber wahrscheinlich an der zu langen Abendschicht und den Akten die sich hier stapeln ... ich werd das heut vormittag durchdenken.
ich bin begeistert ! -
irgendwas rennt falsch: @JeGr
die zu loggenden Clients erhalten mittels CSO
10.0.0.230/24 - 10.0.0.253/24#!/usr/local/bin/php -q <?php require_once("/etc/inc/notices.inc"); $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a'); if ( strrchr (__FILE__ , 'disconnect') ) { $client_ip=getenv(ifconfig_pool_remote_ip); $min_ip="10.0.0.229"; $max_ip="10.0.0.253"; if (ip2long($min_ip) < ip2long($client_ip) && ip2long($client_ip) < ip2long($max_ip)) { $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a') . " \n duration : " . round(((getenv('time_duration'))/3600),2) . " hours, or " . round(((getenv('time_duration'))/60),2) . " minutes, or " . getenv('time_duration') . " seconds,\n upload from vpn-client (received) : " . round(((getenv('bytes_received'))/1048576),2) . " MB, \n download to vpn-client (send) : " . round(((getenv('bytes_sent'))/1048576),2) ." MB. \n DISCONNECTED."; } } notify_all_remote($local_connect_value); ?>
es wird zwar ein mail versendet aber nur mehr mit diesem Inhalt:
client mit 10.0.0.233 (also ein client innerhalb der Range)
client mit 10.0.0.7 (also ein client außerhalb der Range) erhält auch noch immer mail
ich versteh auch nicht wieso diese Zeilen nicht mehr mitübermittelt werden .
für Hinweise dankbar ... wie gesagt irgendwie Wald und Bäume ...
-
du musst vom ersten Aufruf von $local_connect_value bis zum letzten notify_all_remote alles in das IF mit den ip2long Vergleichen packen
Warum:
- du hast vor dem IF noch die erste Anweisung mit dem local_connect_value
- den zweiten Block mit dem local... hast du im IF
- NACH dem IF (also immer!) führst du das notify aus -> mit dem ersten Wert von ganz am Anfang befüllt
Oder verstehe ich dich falsch und es soll immer eine Notification kommen und nur bei den Clients im Range dann eben mehr Details?
Wenn ja, dann würde ich mit
$local_connect_value = "";
anfangen, dann im IF den langen value string reinpacken, einen zusätzlichen Else machen mit nur dem geringen output und am Ende den notify außerhalb des IFs.
-
@JeGr said in scripting / openVPN / emailNotification /:
nein das script soll nur dann einen Versand triggern wenn die IP d vpn-client eine IP aus der RANGE
hat.interner Test wenn die IP fest vergeben funktioniert.
also die IF tut was sie soll (hab ja auch nix anderes erwarte)
und das kommt auch alles so wie es soll.#!/usr/local/bin/php -q <?php require_once("/etc/inc/notices.inc"); $client_ip=getenv(ifconfig_pool_remote_ip); // $client_ip="10.0.0.252"; // be aware range = .250 - .254 $min_ip="10.0.0.250"; $max_ip="10.0.0.255"; if (ip2long($min_ip) < ip2long($client_ip) && ip2long($client_ip) < ip2long($max_ip)) { $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a') . " \n duration : " . round(((getenv('time_duration'))/3600),2) . " hours, or " . round(((getenv('time_duration'))/60),2) . " minutes, or " . getenv('time_duration') . " seconds,\n upload from vpn-client (received) : " . round(((getenv('bytes_received'))/1048576),2) . " MB, \n download to vpn-client (send) : " . round(((getenv('bytes_sent'))/1048576),2) ." MB. \n DISCONNECTED."; notify_all_remote($local_connect_value); } ?>
jetzt kommt der nervige teil (verbindungen aufbauen traffic und closen ... warten ) and again
-
Hmm ich wollte das gerade mal nachbauen aber bei mir werden im Lab überhaupt keine Mails versendet ;)
-
du musst die email notification auf der box aktiviert haben
im trockentest funktioniert die IF
also das schript auf der Konsole aufrufen wenn$client_ip="10.0.0.252";
als fix definiert ist haut es ohne probleme hin
also bei einer IP aus der Range bekommt man ein mail
bei einer die nicht in er Range ist bekommt man keines
(kann man testen indem man) nach der letzten}
folgendes else einsetzt (der einzige Unterschied ist ein zusätzliches ELSE im user-name um im mail eine Unterscheidung zu haben)else $local_connect_value = " \n ELSE-user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a') . " \n duration : " . round(((getenv('time_duration'))/3600),2) . " hours, or " . round(((getenv('time_duration'))/60),2) . " minutes, or " . getenv('time_duration') . " seconds,\n upload from vpn-client (received) : " . round(((getenv('bytes_received'))/1048576),2) . " MB, \n download to vpn-client (send) : " . round(((getenv('bytes_sent'))/1048576),2) ." MB. \n DISCONNECTED."; notify_all_remote($local_connect_value);
sobald man allerdings
$client_ip=getenv(ifconfig_pool_remote_ip);
oder (unterschied sind die beiden
'
)$client_ip=getenv('ifconfig_pool_remote_ip');
aktiviert hat (was man ja sollte) bekommt man gar nix oder einfach immer nur das Ergebnis der ELSE.
Da hats mE was mit der Abfrage / Verwendung / Weiterverarbeitung der IP aus
$client_ip
Variable.nP
-
Ja die Notifications hatten ein Problem, das Zusammenspiel mit STARTTLS ist da wackelig, aber anyway.
Jetzt muss ich nur noch schauen, warum der Disconnect nicht erkannt wird, irgendwas ist da faul. Dann kann ichs endlich mal nachstellen.
-
jop dann wart ich mal geduldig ab ;)
ich vermute das die Verarbeitung der
$client_ip
nicht funktioniert denn der Inhalt dieser Variable wird im ELSE-Teil ja richtig ausgegeben.wenn das Ding fertig ist sollte man es verkaufen !
;)
nP -
So jetzt hab ichs. Skript macht das was ich will ;) was vielleicht etwas anders ist, als was du vor hattest - aber anpassen geht dann relativ einfach.
Was irgendwie gestört hat - konnte ich jetzt nicht rauskitzeln warum - war der IF mit dem "FILE" auf "disconnect". Da aber das ganze Skript ja überhaupt nur beim Disconnect aufgerufen wird (durch OVPN Server Skript), macht das IMHO eh keinen wirklichen Sinn bzw. bringt nutzen - es wird ja so oder so nur beim Disconnect ausgeführt.
Ergo weg damit und jetzt läuft es wie es soll, inkl. Logging ins Syslog zusätzlich zur Mail (falls man es lieber im Log haben will). Wie ich es auf die Schnelle in das OVPN Syslog reinbekomme, hatte ich jetzt nicht gesucht, aber das geht sicher auch irgendwie noch.
-
Script zu finden wo?
Dir ist eh klar das es bei d ergänzen Sache um die Lesbarkeit d Daten geht
Dauer in out user etc. -
Code den ich verwende:
#!/usr/local/bin/php-cgi -q <?php require_once("/etc/inc/notices.inc"); $client_ip=getenv('ifconfig_pool_remote_ip'); $min_ip="172.22.255.229"; $max_ip="172.22.255.254"; //if ( strrchr (__FILE__ , 'disconnect') ) { if (ip2long($min_ip) < ip2long($client_ip) && ip2long($client_ip) < ip2long($max_ip)) { // wenn IP innerhalb der Range ist, dann logge volle Info und sende Mail: $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a') . " \n duration : " . round(((getenv('time_duration'))/3600),2) . " hours, or " . round(((getenv('time_duration'))/60),2) . " minutes, or " . getenv('time_duration') . " seconds,\n upload from vpn-client (received) : " . round(((getenv('bytes_received'))/1048576),2) . " MB, \n download to vpn-client (send) : " . round(((getenv('bytes_sent'))/1048576),2) ." MB. \n DISCONNECTED."; } else { // sonst nur Kurzform loggen und versenden: $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a'); } //} syslog(LOG_USER, "vpnconnect.php: ".$local_connect_value); notify_all_remote($local_connect_value); ?>
Den Min/Max Bereich muss man sich natürlich anpassen wie man Lust hat. Ist die IP aus dem Bereich, gibt es exzessives Logging mit Zusatzdaten, wenn sie nicht im Bereich war, dann gibts nur kleines Logging:
Beispiel: 2 User, jens und test.
jens -> 172.22.255.234
test -> 172.22.255.2Output bei jens:
Notifications in this message: 1 ================================ 16:41:46 user_name: jens vpn_client_ip: 172.22.255.234 connected from 1.2.3.4 on April 21, 2020, 4:41 pm duration : 0.01 hours, or 0.6 minutes, or 36 seconds, upload from vpn-client (received) : 0.04 MB, download to vpn-client (send) : 0 MB. DISCONNECTED.
Output bei test:
Notifications in this message: 1 ================================ 16:43:53 user_name: test vpn_client_ip: 172.22.255.22 connected from 1.2.3.4 on April 21, 2020, 4:43 pm
Will man jetzt bei einer Gruppe gar keine Mail versenden, muss man das nur etwas umgruppieren:
#!/usr/local/bin/php-cgi -q <?php require_once("/etc/inc/notices.inc"); $client_ip=getenv('ifconfig_pool_remote_ip'); $min_ip="172.22.255.229"; $max_ip="172.22.255.254"; if (ip2long($min_ip) < ip2long($client_ip) && ip2long($client_ip) < ip2long($max_ip)) { // wenn IP innerhalb der Range ist, dann logge volle Info und sende Mail: $local_connect_value = " \n user_name: " . getenv('common_name') . " \n vpn_client_ip: " . getenv('ifconfig_pool_remote_ip') ." connected from " . getenv('trusted_ip') . " on " . date('F j, Y, g:i a') . " \n duration : " . round(((getenv('time_duration'))/3600),2) . " hours, or " . round(((getenv('time_duration'))/60),2) . " minutes, or " . getenv('time_duration') . " seconds,\n upload from vpn-client (received) : " . round(((getenv('bytes_received'))/1048576),2) . " MB, \n download to vpn-client (send) : " . round(((getenv('bytes_sent'))/1048576),2) ." MB. \n DISCONNECTED."; syslog(LOG_USER, "vpnconnect.php: ".$local_connect_value); notify_all_remote($local_connect_value); } else { // sonst nichts loggen oder mailen } ?>
Alle anderen Sachen kann man jetzt natürlich noch nach Belieben schön machen. Den Output Salat aufräumen, die Variablen alle sauber vorher zuweisen, etc. etc.
Wenn ich dazu komme räum ich vielleicht nochmal auf und machs schön :D
-
Kleine Anmerkung:
Ich hab mich nochmal hingesetzt und es für mich gerade schön gemacht. Skripte in /usr/local/bin gepackt, Logging neu, Variablen vordefiniert und nicht alles im Sendevorgang gesetzt, Log Output unterschiedlich zum Mail Output etc.
Muss man alles nicht, hatte mich aber getriggert. Kann sich aber jeder selbst zusammenbauen, wie er den Output möchte, da muss ich denke ich nicht nochmal großartig was posten.
Was aber noch schön ist, wenn das wer möchte: Um den Logging Vorgang ins Syslog von OpenVPN zu verfrachten und nicht in das normale Syslog (vielleicht will es ja jemand genau da haben - je nach Gusto), muss man noch folgendes tun:
- Direkt zum Start des Skripts nach dem include ein
openlog("openvpn", LOG_PID | LOG_PERROR, LOG_LOCAL0);
einfügen - Die
syslog(...)
Zeile ändern aufLOG_NOTICE
statt User, das ist generell eh sinnvoller, da wir ja keinen Alarm auslösen wollen - Den Output von
syslog()
sollte man entweder mit<skriptname:>
beginnen (wenns ins syslog geht, dort Standard), oder beim Output ins OVPN Log dann sowas wieLogout:
o.ä. voranstellen, damit man die Logzeile besser rausfiltern kann wenn man sucht. - Am Ende des Skript muss noch eine Zeile
closelog();
mit rein, die dann das Logging abschließt. Mit der Umleitung durchopenlog
und den ersten Parameter "openvpn" landet das ganze dann im OpenVPN Tab/Log als wäre es vom OVPN Prozess selbst gesendet worden.
Das rundet den Feinschliff etwas ab :)
Meine Variante im Lab sieht jetzt so aus (nach einem schnellen internen Test):
Mail:
Log Eintrag:
Man sieht den obersten Eintrag etwas anders formatiert als die Mail um besser im Log lesbar zu sein (und da im Log keine Newlines gelten). Zusätzlich sieht es so aus, als käme die Info vom "openvpn" Prozess, die unterschiedliche PID zeigt aber, dass hier das PHP Skript zu Gange war :)
Grüße
- Direkt zum Start des Skripts nach dem include ein
-
/status ... ich noch immer nicht dazu gekommen ... fffu*****