Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
openvpn callback on demand...
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Deutsche Dokumentation
View previous topic :: View next topic  
Author Message
dambacher
Apprentice
Apprentice


Joined: 11 Feb 2003
Posts: 289
Location: Germany

PostPosted: Thu Dec 29, 2005 9:09 pm    Post subject: openvpn callback on demand... Reply with quote

Es Klappt :!:
Ich habe grade diald, capisuite, openvpn und rp-pppoe zu einer on-demand dsl-tunnel-Lösung kombiniert.

Zwei Rechner an unterschiedlichen Standorten haben sowohl einen dsl als auch einen isdn-Anschluss.
Auf beiden lauscht capisuite am isdn auf eingehende Anrufe.
Bei bestimmten Nummern startet capisuite den Internetzugang.
Dann wartet openvpn auf eine Verbundung.

Der zweite Rechner kann zusätzlich über diald und capisuite den ersten anrufen.
Dann startet diald den Internetzugang und openvpn und voilas die Verbindung steht!

Es brauchte aber ein paar zusätzliche Codezeilen in diald und capisuite.
Wenn jemand an den Details interessiert ist... einfach rückmailen

Guten Rutsch!
Back to top
View user's profile Send private message
manuels
Advocate
Advocate


Joined: 22 Nov 2003
Posts: 2146
Location: Europe

PostPosted: Thu Dec 29, 2005 10:49 pm    Post subject: Reply with quote

Quote:
Wenn jemand an den Details interessiert ist... einfach rückmailen

RÜCKMAIL!

hört sich interressant an.
der held des ausklingenden jahres wärst du, wenn du ein howto schreiben würdest! :wink:

Tschö mt ö
Manuel
_________________
Build your own live cd with catalyst 2.0!
Back to top
View user's profile Send private message
dambacher
Apprentice
Apprentice


Joined: 11 Feb 2003
Posts: 289
Location: Germany

PostPosted: Fri Dec 30, 2005 8:40 am    Post subject: Reply with quote

OK, überredet!

Also der Reihe nach:

Für die Installation von rp-pppoe und dsl gibt es gute Dokumentation, danach bin ich auch vorgegangen.
Auch zur Installation in Inbetriebnahme von openvpn gibt es ein gutes HOWTO.

Meine Lösung basiert darauf, dass ich beiden Server-Rechnern eine feste IP-Adresse erkauft habe.
(Dadurch spare ich mir das Übermitteln der IP während des Telefonanrufes)

Als Beispiel: auf dem Server sehen meine local.conf folgendermaßen aus:
Für die "roadwarrior"-Einwahl:
Code:

# config for openvpn connection vpn
dev tun1
tls-server
ca /etc/certs/ca.crt
cert /etc/certs/server.crt
key /etc/keys/server.key  # This file should be kept secret
dh /etc/openvpn/certs/dh1024.pem
port 1194
local 217.xx.xx.xx
server 192.168.4.0 255.255.255.0
push "route 192.168.0.0 255.255.255.0"
keepalive 10 120
ping-timer-rem

und für die automatische Einwahl
Code:

# config for openvpn on demand connection
dev tun0
tls-server
tls-remote my_client
ca /etc/certs/ca.crt
cert /etc/certs/server.crt
key /etc/keys/server.key  # This file should be kept secret
dh /etc/openvpn/certs/dh1024.pem
local 217.xx.xx.xx
port 1195
ifconfig 192.168.5.2 192.168.5.1
route 192.168.1.0 255.255.255.0
keepalive 10 120
ping-timer-rem


Ein Client bekommt folgende Konfiguration
Code:

dev tun
tls-client
ca /etc/certs/ca.crt
cert /etc/certs/laptop.crt
key /etc/keys/laptop.key
remote 217.xx.xx.xx
tls-remote server
pull
Back to top
View user's profile Send private message
dambacher
Apprentice
Apprentice


Joined: 11 Feb 2003
Posts: 289
Location: Germany

PostPosted: Fri Dec 30, 2005 8:54 am    Post subject: Reply with quote

Jetzt zum den individuellen Anpassungen.

Zunächst zu capisuite.
Um einen Anruf abzupassen und Aktionen auszuführen ist das incomming-script nötig. Ich habe das Default skript durch folgendes ersetzt:
Code:

# implement simple callback to internet function
# Iniziiere internetverbindung wenn bestimmter Anschluss anruft.
# Danach kann mit vpn ein Zugang hergestellt werden...

import os, string, capisuite, commands

numbers="hier stehen meine erlaubten Telefonnummern mit komma getrennt"
msn="meine msn"

def callIncoming(call,service,call_from,call_to):
   if  (call_from not in numbers.split(',') or call_to!=msn):
      capisuite.log("call from "+call_from+" to "+call_to+" ignoring",1,call)
      capisuite.reject(call,0x3495)
      return

   # Wenn menschlicher Anrufer, dann Rueckmeldung
   if (service==capisuite.SERVICE_VOICE):
      capisuite.log("call from "+call_from+" to "+call_to+" accepted",1,call)
           capisuite.connect_voice(call,2)
           capisuite.audio_send(call,"/usr/share/capisuite/beep.la")
   else:
           capisuite.reject(call,0x3490)
        capisuite.disconnect(call)

   # Starte Verbindung
   erg=commands.getoutput("ping -c 4 www.t-com.de")
   capisuite.log("ping command output: "+erg,1,call)
   erg=commands.getoutput("logger \"capisuite initiated connection\" ")
   capisuite.log("logger command output: "+erg,1,call)


Das Skript testet, ob die Nummer gelistet ist. Wenn ja startet es ein Ping zur Interneteinwahl und gibt ein "beep" aus.

Nun musste ich feststellen, das das idle-skript nicht auf Kommando zum Laufen gebacht werden konnnte. Und einen Dauerlauf alle 2s
ist zu viel und 30s waren zu lange. Also habe ich capisuite gepatch um das Skript auf Signal SIGUSR1 zu starten. Zusätzlich kann ich im Skript Abfragen, ob der Start erzwungen war oder nicht.
Der Patch dazu ist hier:
Code:

Nur in capisuite-0.4.5u1/scripts: capisuitefax.
diff -ur capisuite-0.4.5/src/application/capisuite.cpp capisuite-0.4.5u1/src/application/capisuite.cpp
--- capisuite-0.4.5/src/application/capisuite.cpp   2004-11-28 14:35:24.000000000 +0100
+++ capisuite-0.4.5u1/src/application/capisuite.cpp   2005-12-25 17:25:13.000000000 +0100
@@ -47,6 +47,14 @@
       capisuiteInstance->reload();
    signal(SIGHUP,hup_handler);
 }
+
+void usr1_handler(int)
+{
+   if (capisuiteInstance)
+      capisuiteInstance->forceIdleRun();
+   signal(SIGUSR1,usr1_handler);
+}
+
 
 CapiSuite::CapiSuite(int argc,char **argv)
 :capi(NULL),waiting(),config(),idle(NULL),py_state(NULL),debug(NULL),error(NULL),finish_flag(false),custom_configfile(),daemonmode(false)
@@ -129,6 +137,7 @@
       signal(SIGTERM,exit_handler);
       signal(SIGINT,exit_handler);  // this must be located after pyhton initialization
       signal(SIGHUP,hup_handler);
+      signal(SIGUSR1,usr1_handler);
    }
         catch (CapiError e) {
       capisuiteInstance=NULL;
@@ -199,6 +208,21 @@
       idle->activate();
 }
 
+void CapiSuite::forceIdleRun()
+{
+   if (debug_level >= 2)
+      (*debug) << prefix() << "forced start of idle script" << endl;
+   if (idle)
+      idle->forceRun();
+}
+
+bool CapiSuite::idleRunWasForced() {
+   if (idle)
+      return idle->runWasForced();
+   else
+      return false;
+}
+             
 void
 CapiSuite::callWaiting (Connection *conn)
 {
diff -ur capisuite-0.4.5/src/application/capisuite.h capisuite-0.4.5u1/src/application/capisuite.h
--- capisuite-0.4.5/src/application/capisuite.h   2004-11-28 14:35:24.000000000 +0100
+++ capisuite-0.4.5u1/src/application/capisuite.h   2005-12-25 15:53:57.000000000 +0100
@@ -114,6 +114,14 @@
       */
       void reload();
 
+      /** @brief force run of idle script on SIGUSR1
+      */
+      void forceIdleRun();
+      
+      /** @brief check if Idle was forced to run
+      */
+      bool idleRunWasForced();
+
       /** @brief print a message to the log
 
           Prints message to the log if it's level is high enough.
@@ -162,7 +170,6 @@
 
       map<string,string> config; ///< holds the configuration read from the configfile
       string custom_configfile; ///< holds the name of the custom config file if given
-
 };
 
 #endif
diff -ur capisuite-0.4.5/src/application/capisuitemodule.cpp capisuite-0.4.5u1/src/application/capisuitemodule.cpp
--- capisuite-0.4.5/src/application/capisuitemodule.cpp   2004-11-28 14:35:25.000000000 +0100
+++ capisuite-0.4.5u1/src/application/capisuitemodule.cpp   2005-12-25 17:28:23.000000000 +0100
@@ -915,6 +915,16 @@
    return (result);
 }
 
+static PyObject*
+capisuite_forced_run(PyObject*, PyObject *args)
+{
+  PyArg_NoArgs(args);
+  if (capisuiteInstance->idleRunWasForced())
+    Py_RETURN_TRUE;
+  else
+    Py_RETURN_FALSE;
+}
+
 
 /** PCallControlMethods - array of functions in module capisuite
 */
@@ -935,6 +945,7 @@
    {"read_DTMF",      capisuite_read_DTMF,      METH_VARARGS, "Read and clear received DTMF. For further details see capisuite module reference."},
    {"log",         capisuite_log,         METH_VARARGS, "Write log message. For further details see capisuite module reference."},
    {"error",      capisuite_error,      METH_VARARGS, "Write error message. For further details see capisuite module reference."},
+   {"forced_run",      capisuite_forced_run,      METH_NOARGS, "Check if idle script was forced to run via SIGUSR. For further details see capisuite module reference."},
         {NULL,NULL,0,NULL}
 };
 
@@ -977,7 +988,6 @@
    }
 }
 
-
 /* History
 
 $Log: capisuitemodule.cpp,v $
diff -ur capisuite-0.4.5/src/application/idlescript.h capisuite-0.4.5u1/src/application/idlescript.h
--- capisuite-0.4.5/src/application/idlescript.h   2004-11-28 14:35:24.000000000 +0100
+++ capisuite-0.4.5u1/src/application/idlescript.h   2005-12-25 17:34:16.000000000 +0100
@@ -82,6 +82,12 @@
       */
       void activate(void);
 
+      /** @brief force run of idle script (e.g. for user signals)
+      */
+      void forceRun(void);
+
+      bool runWasForced(void);
+
    private:
       /** @brief Thread body. Calls the python function idle().
 
@@ -109,8 +115,10 @@
       int idlescript_interval; ///< interval between subsequent executions of idle script
       Capi *capi; ///< reference to Capi object
       bool active; ///< used to disable IdleScript in case of too much errors
-      
+      bool forced; ///< used to force run of IdleScript
       pthread_t thread_handle; ///< handle for the created pthread thread
+      pthread_mutex_t idle_mut; //< mutex for forced run of IdleScript
+      pthread_cond_t idle_cond; //< condition for forced run of IdleScript
 };
 
 #endif



Wie man den patch einspielt? Durch einen Trick. Ich juble ebuild meinen Patch einfach unter, weil ich zu faul bin einen eigenen ebuild zu schreiben.
Code:

ebuild /usr/portage/net-dialup/capisuite/capisuite-0.4.5.ebuild unpack
cd /var/lib/portage/capisuite-0.4.5/work
patch -p0 < capisuite-0.4.5-u1.patch
ebuild /usr/portage/net-dialup/capisuite/capisuite-0.4.5.ebuild compile install qmerge


Danach kann ich mein idle-skript auf der client-Seite wie folgt erstellen:
Code:

# idle script fuer client

import os, string, capisuite

my_nr="hier meine msn"
callback_nr="hier die anzurufende Nummer"

def idle(capi):
   capisuite.log("idle script running",2)
   if (capisuite.forced_run()):
      capisuite.log("idle script forced to run",2)
      capisuite.log("initiating callback for server...",1)
      (call,result)=capisuite.call_voice(capi,1,my_nr,callback_nr,20,0)
      if (result!=0):
         capisuite.log("...no success! Error is 0x%x" % result,1)
      else:
         capisuite.log("...success!",1)
         capisuite.disconnect(call)
   return



Es testet zunächst, ob es normal oder per Signal gestartet wurde. Wenn das Signal kam, wählt es die gewünschte Nummer und wartet auf eine erfolgreiche Antwort, legt dann gleich auf. Voila!

(Hier könnte man jetzt auch eine Übermittlung dynamischer ip-Adressen per dialtone einbauen...)


Last edited by dambacher on Fri Dec 30, 2005 9:21 am; edited 1 time in total
Back to top
View user's profile Send private message
dambacher
Apprentice
Apprentice


Joined: 11 Feb 2003
Posts: 289
Location: Germany

PostPosted: Fri Dec 30, 2005 9:13 am    Post subject: Reply with quote

Jetzt zu diald.
Auch hier musste ich ein bisschen hand anlegen, denn diald startet seine skripten erst, wenn es ein funktionierendes netzwerkgerät hat. openvpn macht das aber erst, wenn der link steht. Hier beisst sich die Katze in den Schwanz :D

In diald gibt eis eine undokumentierte skripting-Funktion, mit der man alles routing selber machen kann.
Also habe ich diald dazu gebracht diese Funktion aufzurufen, wenn es ein funktionierendes device haben will.
Den Patch dazu habe ich unten. Mit dem vorher beschriebenen Trick installiert man das ganze. Nicht wundern. Ein paar hunks macht gentoo auch schon, die sind doppelt...
Code:

diff -ur diald-1.0/dev.c diald-1.0ud1/dev.c
--- diald-1.0/dev.c   2001-06-16 21:51:39.000000000 +0200
+++ diald-1.0ud1/dev.c   2005-12-29 16:01:20.000000000 +0100
@@ -33,6 +33,14 @@
     rx_count = -1;
     mon_syslog(LOG_INFO, "Open device %s", current_dev);
     dead = 0;
+
+    /* call ifsetup to maybe create interface */
+    if (ifsetup) {
+      char buf[1024];
+      sprintf(buf, "%s create link %s",
+         ifsetup, current_dev);
+      run_shell(SHELL_WAIT, "create link", buf, -1);
+    }
 }
 
 /*
@@ -226,6 +234,13 @@
    req_pid = 0;
    dead = 1;
     }
+    /* call ifsetup to maybe destroy interface */
+    if (ifsetup) {
+      char buf[1024];
+      sprintf(buf, "%s destroy link %s",
+         ifsetup, current_dev);
+      run_shell(SHELL_WAIT, "destroy link", buf, -1);
+    }
 }
 
 void dev_reroute()
@@ -260,6 +275,13 @@
    req_pid = 0;
    dead = 1;
     }
+    /* call ifsetup to maybe destroy interface */
+    if (ifsetup) {
+      char buf[1024];
+      sprintf(buf, "%s destroy link %s",
+         ifsetup, current_dev);
+      run_shell(SHELL_WAIT, "destroy link", buf, -1);
+    }
 }
 
 void dev_zombie()
diff -ur diald-1.0/diald.h diald-1.0ud1/diald.h
--- diald-1.0/diald.h   2001-06-16 18:01:25.000000000 +0200
+++ diald-1.0ud1/diald.h   2005-12-29 16:03:53.000000000 +0100
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
+#include <time.h>
 #if HAVE_UNISTD_H
 #  include <unistd.h>
 #endif
diff -ur diald-1.0/firewall.c diald-1.0ud1/firewall.c
--- diald-1.0/firewall.c   2001-06-16 21:51:39.000000000 +0200
+++ diald-1.0ud1/firewall.c   2005-12-29 16:06:06.000000000 +0100
@@ -69,7 +69,7 @@
 #if 0
     mon_syslog(LOG_DEBUG,"slot def: %d %d %x %x %x",
    slot->start, slot->end, slot->wday, slot->mday, slot->month);
-#endif 0
+#endif
    if ((slot->start <= ctime)
    &&  (ctime <= slot->end)
    &&  (slot->wday & (1<<ltime->tm_wday))
diff -ur diald-1.0/log.c diald-1.0ud1/log.c
--- diald-1.0/log.c   2001-06-16 21:51:39.000000000 +0200
+++ diald-1.0ud1/log.c   2005-12-29 16:17:06.000000000 +0100
@@ -14,7 +14,7 @@
 
 #include <diald.h>
 
-
+#if 0
 static char *
 xstrerror(int n)
 {
@@ -25,7 +25,9 @@
     sprintf(buf, "Error code %d\n", n);
     return buf;
 }
-
+#else
+#define xstrerror(x) strerror(x)
+#endif
 
 void
 mon_syslog(int pri, char *fmt, ...)
diff -ur diald-1.0/timer.c diald-1.0ud1/timer.c
--- diald-1.0/timer.c   2001-06-16 22:16:22.000000000 +0200
+++ diald-1.0ud1/timer.c   2005-12-29 16:08:37.000000000 +0100
@@ -90,9 +90,9 @@
 
 int validate_function(struct timer_lst *c)
 {
-   if (c->function == del_impulse
-   || c->function == del_connection
-   || c->function == slip_start_fail)
+   if (c->function == (void*)(void*)del_impulse
+   || c->function == (void*)(void*)del_connection
+   || c->function == (void*)(void*)slip_start_fail)
       return 1;
    mon_syslog(LOG_ERR, "Caught a bad function value %p. Tell Eric.\n",
       c->function);



Die Konfigurationsdatei von diald sieht wie folgt aus:
Code:

#diald.conf
mode dev
device tun0
ifsetup "/etc/diald/ifsetup_openvpn.sh"
local <client-ip>
remote <server-ip>
connect-timeout 90
redial-timeout 10
retry-count 3
demand
# 10min timeout fuer alle ssh
accept tcp 600 tcp.dest=tcp.ssh
accept tcp 600 tcp.source=tcp.ssh
# 2min fuer Druckjobs...
keepup tcp 120 tcp.source=tcp.printer
keepup tcp 120 tcp.source=631
keepup udp 120 tcp.source=631
accept any 30 any


Wichtig ist der Eintrag des ifsetup-skriptes. Hier kann man jetzt nach herzenslust das routing verändern.
Mein Skript sieht folgendermaßen aus.
Code:

#!/bin/bash

logger "starting $0 $@ ..."

MY_DIR=$(dirname $0)

FUNCTION=$1
MODE=$2
INTERFACE=$3

case $FUNCTION in
    start)
   case $MODE in
       proxy)
      ifconfig $INTERFACE 192.168.1.254 pointopoint 192.168.0.254 up
      ;;
   esac
   ;;
    stop)
   case $MODE in
       proxy)
      ifconfig $INTERFACE down
      ;;
   esac
   ;;
    create)
   case $MODE in
       link)
                  logger -- "start_openvpn.sh: starting openvpn connection"
                  #hier muss ein Kommando hin zum Anwaehlen des Rechnes, aber welches?
                  killall -USR1 capisuite
                  #internetverbindung starten
                  ping -c 4 www.t-com.de 2>&1 >/dev/null
                  #openvpn starten
                  openvpn --daemon --config /etc/openvpn/dialin.conf
      ;;
   esac
   ;;
    destroy)
   case $MODE in
       link)
                  logger -- "stop_openvpn.sh: stopping openvpn connection"
                  kill  $(cat /var/run/openvpn_dialin.pid)
      ;;
   esac
   ;;
esac


Meine openvpn-konfiguration für die Einwahl sieht dann so aus. Wichtig ist die writepid-Zeile am ende!
Code:

# client configuration
dev tun0
tls-client
tls-remote server
ca /etc/openvpn/certs/ca.crt
cert /etc/openvpn/certs/client.crt
key /etc/openvpn/keys/client.key
port 1195
local 217.xx.xx.xx.xx
remote 217.xx.xx.xx.xx
ifconfig 192.168.5.1 192.168.5.2
route 192.168.0.0 255.255.255.0
writepid /var/run/openvpn_dialin.pid


So. Jetzt sollte das ganze soweit sein.
diald, openvpn und capisuite weden per rc-update in das default-profiil gebracht und der Test kann beginnen.
Ich bastle jetzt noch an den Timeout-Einstellungen rum. Eventuell brauche ich für das ifsetup-skript noch einen
Locking-Mechanismus.
Aber zunächst läuft alles mal.
Die Patches versuche grade an die maintainer der Programme weiterzuleiten...

Grüße
dambacher
Back to top
View user's profile Send private message
dambacher
Apprentice
Apprentice


Joined: 11 Feb 2003
Posts: 289
Location: Germany

PostPosted: Fri Dec 30, 2005 9:24 am    Post subject: Reply with quote

Kann eigentlich jemand dem Forum eine deutsche tippkorrektur einbauen? :)
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Deutsche Dokumentation All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum