Puncte:1

Freeradius cu serverul dhcp: Apelurile la modulul perl returnează eroare

drapel us

Aceasta este o continuare a întrebării mele anterioare în trimiterea rutelor statice de la implementarea serverului DHCP Freeradius în combinație cu serverul Strongswan VPN.

Când depanez Freeradius folosind tcpdump și Wireshark, am aflat că pot trimite rute statice fără clasă de pe serverul DHCP Freeradius prin adăugarea DHCP-Classless-Static-Route și DHCP-Site-specific-25 (aka Microsoft static route) opțiuni la mine DHCP-Descoperire și Solicitare DHCP secțiuni ale fișierului de configurare a serverului dhcp.

Cu toate acestea: Se pare că rutele statice nu sunt acceptate de clientul Microsoft VPN dacă setez gateway-ul implicit să fie 0.0.0.0 după cum sugerează Documentație Strongswan.

Cel puțin nu pot găsi rutele anunțate pe clientul meu Windows când folosesc imprimare traseu -4.

De asemenea, nu pot adăuga rutele manual pe clientul Windows când folosesc 0.0.0.0 ca gateway standard prin interfața VPN.

In orice caz:

Să spunem că vreau să accesez subrețeaua 192.168.200.0/24 prin VPN și serverul meu VPN atribuie adresa 192.168.201.2/24 către clientul meu Windows. Apoi, este de fapt posibil să creați o rută statică pe partea clientului Windows declarând că subrețeaua 192.168.200.0/24 este accesibilă prin 192.168.201.2 folosind comanda Windows:

traseu adauga 192.168.200.0 masca 255.255.255.0 192.168.201.2

Știu că pare puțin ciudat, dar pot da ping oricărei gazde de pe 192.168.200.0 subrețea, așa că atâta timp cât funcționează sunt fericit. :-)

Dar: m-aș bucura mai mult dacă aș putea face același lucru făcând publicitate rutelor de pe serverul meu VPN, în loc să o fac manual pe toți clienții VPN. :-)

Asta înseamnă că trebuie să fac un pic de programare dinamică la configurația DHCP în Freeradius. În cazul meu, înseamnă că trebuie să fac o referire la un modul perl în DHCP-Discover și DHCP-request care preia adresa IP vpn client alocată, o convertesc în octeți și o combin cu rutele statice care sunt, de asemenea, date ca octeți.

Un exemplu:

Subrețeaua 192.168.200.0/24 va fi codificat ca 0x18c0a8c8 ca masca de subrețea este mai întâi codificată.

Clientul 192.168.201.2/24 va fi codificat ca 0xc0a8c902 deoarece doar convertește fiecare număr din adresa IP în hex.

Codificarea finală pentru traseu va fi: 0x18c0a8c8c0a8c902 întrucât este doar o concatinare a celor două șiruri.

Apoi trebuie să folosesc actualizați răspunsul cu urmatorul cod:

  actualizare răspuns {
    &DHCP-Classless-Static-Route = 0x18c0a8c8c0a8c902
    &DHCP-Site-specific-25 = 0x18c0a8c8c0a8c902
  }

Dacă există mai multe rute, atunci toate rutele vor fi concatenate într-un șir lung.

Partea dificilă:

Să presupunem că aveți configurația implicită a serverului DHCP Freeradius așa cum se găsește în freeradius/3.0/sites-available/dhcp fişier.

Structura generală a fișierului pentru DHCP-Discover și DHCP-Request este următoarea:

dhcp DHCP-Request {
  actualizare răspuns {
    &DHCP-Message-Type = DHCP-Ack
  }

  actualizare răspuns {
    # Opțiuni generale DHCP, cum ar fi GW implicit, DNS, durata de închiriere a adresei IP etc.
  }

  controlul actualizării {
    &Pool-Name := „vpn_pool”
  }

  dhcp_sqlippool

  Bine
}

Apoi, din câte am adunat, trebuie să îmi apelez modulul perl după dhcp_sqlippool a fost sunat și înainte de a se întoarce Bine, deoarece dhcp_sqlippool este modulul care atribuie adresa IP clientului VPN.

Asta înseamnă că versiunea mea ar fi ceva de genul:

dhcp DHCP-Request {
  actualizare răspuns {
    &DHCP-Message-Type = DHCP-Ack
  }

  actualizare răspuns {
    # Opțiuni generale DHCP, cum ar fi GW implicit, DNS, durata de închiriere a adresei IP etc.
  }

  controlul actualizării {
    &Pool-Name := „vpn_pool”
  }

  dhcp_sqlippool

  perl

  # Dacă modulul perl nu a returnat nicio eroare
  dacă(ok) {
    actualizare răspuns {
      # Perl-Route conține un șir codificat hex cu toate rutele.
      &DHCP-Classless-Static-Route = Rută-Perl
      &DHCP-Site-specific-25 = Perl-Route      
    }
  }

  # Nu sunteți sigur dacă acesta este necesar?
  actualizare răspuns {
    &DHCP-End-Options = 255
  }

  Bine
}

Pentru ca acesta să funcționeze, trebuie să activez perl sub freeradius/3.0/mods-enabled folder și modificați numele fișierului în freeradius/3.0/mods-enabled/perl să-l îndrept către modulul meu perl. Ca de exemplu:

nume fișier = ${modconfdir}/${.:instance}/dhcp/Options.pm

Dar cum fac referire la apelul către perl în mod corect?

Am crezut că trebuie să activez linia func_post_auth = post_auth în freeradius/3.0/mods-enabled/perl și creează un sub post_auth secțiunea din modulul meu perl pentru a gestiona apelurile de la Freeradius, dar din câte văd în jurnalul meu, primesc următoarea eroare în Freeradius:

(8) perl: perl_embed:: module = /etc/freeradius/3.0/mods-config/perl/dhcp/Options.pm , 
func = post_auth exit status= Subrutină nedefinită &main::post_auth apelată.
...
(8) [perl] = eșec
(8) } # dhcp DHCP-Discover = eșec

Deci ce este ceea ce nu văd?

Puncte:0
drapel us

M-am lovit cu capul de perete de câteva ori, dar cel puțin am făcut ca modulul perl să funcționeze, deși nu sunt complet unde vreau să fiu, deoarece rutarea statică prin DHCP nu trece de la serverul DHCP Freeradius la clientul VPN prin Strongswan , dar depanarea pachetelor UDP de pe serverul DHCP Freeradius implică că problema se află în altă parte.

Oricum, iată ce am făcut:

  1. Activați modulul perl în freeradius/3.0/mods-enabled și setați cel puțin următoarele linii:
perl {
  # Locația codului Perl: ("freeradius/3.0/mods-config/dhcp/Options.pm")
  nume fișier = ${modconfdir}/${.:instance}/dhcp/Options.pm

  # Modulul DHCP este apelat în timpul freeradius post_auth
  func_post_auth = post_auth
}
  1. Modifica freeradius/3.0/sites-enabled/dhcp Locurile relevante sunt DHCP-Descoperire și Solicitare DHCP:
dhcp DHCP-Descoperire {

        actualizare răspuns {
               DHCP-Message-Type = DHCP-Ofertă
        }

        # Conținutul de aici este inventat. Schimbă-le!
        actualizare răspuns {
                &DHCP-Domain-Name-Server = 192.168.200.1
                &DHCP-Subnet-Mask = 255.255.255.0
                &DHCP-IP-Address-Lease-Time = 86400
                &DHCP-DHCP-Server-Identifier = 192.168.200.4
        }

        # Sau alocați IP-uri din pool-ul DHCP în SQL. Poate ai nevoie
        # setați aici numele piscinei dacă nu l-ați setat în altă parte.
        controlul actualizării {
                &Pool-Name := „vpn_pool”
        }

        dhcp_sqlippool

        # Apelați generarea rutei statice.
        perl

        Bine
}

dhcp DHCP-Request {

        # Tip de pachet de răspuns.Consultați secțiunea DHCP-Discover de mai sus.
        actualizare răspuns {
               &DHCP-Message-Type = DHCP-Ack
        }

        # Conținutul de aici este inventat. Schimbă-le!
        actualizare răspuns {
                &DHCP-Domain-Name-Server = 192.168.200.1
                &DHCP-Subnet-Mask = 255.255.255.0
                &DHCP-IP-Address-Lease-Time = 86400
                &DHCP-DHCP-Server-Identifier = 192.168.200.4
        }

        # Sau alocați IP-uri din pool-ul DHCP în SQL. Poate ai nevoie
        # setați aici numele piscinei dacă nu l-ați setat în altă parte.
        controlul actualizării {
                &Pool-Name := „vpn_pool”
        }
 
        dhcp_sqlippool

        # Apelați generarea rutei statice.
        perl

        Bine
}
  1. Creați codul perl situat la freeradius/3.0/mods-config/perl/dhcp/Options.pm:
folosiți strict;
folosiți avertismente;
utilizați Data::Dumper;
utilizați Net::IP;

# Aduceți hashurile globale în domeniul pachetului
nostru (%RAD_REQUEST, %RAD_REPLY, %RAD_CHECK);

#
# Aceasta este remaparea valorilor returnate
#
folosește constant {
    RLM_MODULE_REJECT => 0, # respinge imediat cererea
    RLM_MODULE_OK => 2, # modulul este OK, continua
    RLM_MODULE_HANDLED => 3, # modulul a gestionat cererea, deci opriți
    RLM_MODULE_INVALID => 4, # modulul consideră cererea nevalidă
    RLM_MODULE_USERLOCK => 5, # respinge cererea (utilizatorul este blocat)
    RLM_MODULE_NOTFOUND => 6, # utilizator nu a fost găsit
    RLM_MODULE_NOOP => 7, # modul a reușit fără a face nimic
    RLM_MODULE_UPDATED => 8, # OK (perechi modificate)
    RLM_MODULE_NUMCODES => 9 # Câte coduri de returnare există
};

# La fel ca src/include/radiusd.h
utilizați constanta L_DBG => 1;
utilizați constanta L_AUTH => 2;
utilizați constanta L_INFO => 3;
utilizați constanta L_ERR => 4;
utilizați constanta L_PROXY => 5;
utilizați constanta L_ACCT => 6;

# Funcție pentru a gestiona post_auth

sub post_auth {

    # Obțineți IP-ul clientului VPN de la serverul DHCP Freeradius.
    my $client_ip = new Net::IP ( $RAD_REQUEST{'DHCP-Requested-IP-Address'} ) sau die (Net::IP::Error());

    # Un exemplu de 2 reguli de rutare trimise („192.168.20.0/24” și „192.168.200.0/24”) 
    my @routes = (net nou::IP('192.168.20/24'), net net::IP('192.168.200/24'));

    # Măsurați câte elemente există în matricea de rute.
    my $size = @routes;

    # Convertiți ip-ul clientului în cod hex.
    my $client_octets = get_ip_octets ($client_ip->ip(),$client_ip->prefixlen());

    # Freeradius vrea ca șirul codificat să înceapă cu „0x”
    # urmat de octeții codificați ca hex.
    my $octet_str = "0x";

    pentru ($i meu = 0; $i < $dimensiune; $i++)
    {
        # Convertiți subrețeaua în octeți, sărind zerourile de sfârșit.
        my $route_octets = get_ip_octets ($routes[$i]->ip(),$routes[$i]->prefixlen());

        # Convertiți prefixul de rețea în octeți
        my $hex_prefix = sprintf("%02x", $routes[$i]->prefixlen());

        # Ruta este codificată de octeți de rețea urmați de octeți de subrețea
        $route_octets = $hex_prefix . $route_octete;

        # Întregul șir de rută este octeții de rută urmați de octeți de gateway („client vpn ip”).
        my $route_str = $route_octets . $octeți_client;

        $octet_str = $octet_str . $route_str;
    }

    # Rutare statică fără clasă (opțiunea dhcp 121)
    $RAD_REPLY{'DHCP-Classless-Static-Route'} = $octet_str;

    # Rutare statică fără clasă Microsoft (opțiunea dhcp 249)
    $RAD_REPLY{'DHCP-Site-specific-25'} = $octet_str;

    returnează RLM_MODULE_OK;

}

sub get_ip_octets {
    # Primul parametru: adresa IP sursă
    my $sip = $_[0];

    # Al doilea parametru: lungimea de biți a rețelei (alias notația CIDR).
    my $cidr = $_[1];

    my @zecimals = split('\.', $sip);
    my $index = int($cidr / 8) ;

    my $result = '';
    pentru ($i meu = 0; $i < $index; $i++)
    {
        # Convertiți fiecare număr din adresa IP în hexadecimal și formatați cu lider
        # zero în cazul în care numărul convertit este mai mic de 16.
        $rezultat = $rezultat . sprintf("%02x", $zecimale[$i]);
    }

    returnează $rezultat;
}

Codul perl poate fi modificat de aici, deci opțiunea 121 sau opțiunea 249 este trimisă în funcție de sistemul de operare client.

De asemenea, las posibilitatea de a face codul mai generic, astfel încât rutele statice pot fi definite direct în fișierul de configurare Freeradius cititorului.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.