AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / server / Perguntas / 1098827
Accepted
Lasse Michael Mølgaard
Lasse Michael Mølgaard
Asked: 2022-04-18 12:17:37 +0800 CST2022-04-18 12:17:37 +0800 CST 2022-04-18 12:17:37 +0800 CST

Freeradius com servidor dhcp: chamadas para o módulo perl retornam erro

  • 772

Esta é uma continuação da minha pergunta anterior no envio de rotas estáticas da implementação do servidor Freeradius DHCP em combinação com o servidor Strongswan VPN.

Ao depurar o Freeradius usando o tcpdump e o Wireshark, descobri que posso enviar rotas estáticas sem classes do servidor DHCP do Freeradius adicionando DHCP-Classless-Static-Routee DHCP-Site-specific-25(também conhecido como rota estática da Microsoft) opções para minhas DHCP-Discovere DHCP-Requestseções do arquivo de configuração do servidor dhcp.

No entanto: Parece que as rotas estáticas não são aceitas pelo cliente VPN da Microsoft se eu definir o gateway padrão 0.0.0.0como sugerido pela documentação do Strongswan .

Pelo menos não consigo encontrar as rotas anunciadas no meu cliente Windows ao usar o route print -4.

Também não consigo adicionar as rotas manualmente no cliente Windows quando estou usando 0.0.0.0como gateway padrão sobre a interface VPN.

No entanto:

Digamos que eu queira acessar a sub -rede 192.168.200.0/24pela VPN e meu servidor VPN atribua o endereço 192.168.201.2/24ao meu cliente Windows. Então é realmente possível criar uma rota estática no lado do cliente Windows declarando que a sub-rede 192.168.200.0/24 é acessível via 192.168.201.2 usando o comando windows:

route add 192.168.200.0 mask 255.255.255.0 192.168.201.2

Eu sei que parece um pouco estranho, mas posso fazer ping em qualquer host na 192.168.200.0sub-rede, então, desde que funcione, estou feliz. :-)

Mas: eu ficaria mais feliz se pudesse fazer a mesma coisa anunciando as rotas do meu servidor VPN em vez de fazê-lo manualmente em todos os clientes VPN. :-)

Isso significa que eu tenho que fazer um pouco de programação dinâmica para a configuração do DHCP no Freeradius. No meu caso, significa que tenho que fazer uma referência a um módulo perl em DHCP-Discover e DHCP-request que pega o endereço IP vpn do cliente atribuído, converte-o em octetos e combina-o com as rotas estáticas que também são fornecidas como octetos.

Um exemplo:

A sub -rede 192.168.200.0/24será codificada como 0x18c0a8c8a máscara de sub-rede é codificada primeiro.

O cliente 192.168.201.2/24será codificado como se estivesse 0xc0a8c902apenas convertendo cada número no endereço IP para hexadecimal.

A codificação final para a rota será: 0x18c0a8c8c0a8c902pois é apenas uma concatinação das duas strings.

Então eu tenho que usar update replycom o seguinte código:

  update reply {
    &DHCP-Classless-Static-Route = 0x18c0a8c8c0a8c902
    &DHCP-Site-specific-25 = 0x18c0a8c8c0a8c902
  }

Se houver mais rotas, todas as rotas serão concatenadas em uma longa string.

A parte complicada:

Suponha que você tenha a configuração padrão do servidor DHCP do Freeradius conforme encontrado no freeradius/3.0/sites-available/dhcparquivo.

A estrutura geral do arquivo para DHCP-Discover e DHCP-Request é a seguinte:

dhcp DHCP-Request {
  update reply {
    &DHCP-Message-Type = DHCP-Ack
  }

  update reply {
    # General DHCP options, such as default GW, DNS, IP-address lease time etc.
  }

  update control {
    &Pool-Name := "vpn_pool"
  }

  dhcp_sqlippool

  ok
}

Então, pelo que entendi, preciso chamar meu módulo perl depois de dhcp_sqlippoolter sido chamado e antes de retornar ok, porque dhcp_sqlippoolé o módulo que atribui o endereço IP ao cliente VPN.

Isso significa que minha versão seria algo como:

dhcp DHCP-Request {
  update reply {
    &DHCP-Message-Type = DHCP-Ack
  }

  update reply {
    # General DHCP options, such as default GW, DNS, IP-address lease time etc.
  }

  update control {
    &Pool-Name := "vpn_pool"
  }

  dhcp_sqlippool

  perl

  # If perl module returned no error
  if(ok) {
    update reply {
      # Perl-Route contains a hex encoded string with all routes.
      &DHCP-Classless-Static-Route = Perl-Route
      &DHCP-Site-specific-25 = Perl-Route      
    }
  }

  # Not sure if this one is needed?
  update reply {
    &DHCP-End-Of-Options = 255
  }

  ok
}

Para fazê-lo funcionar, eu tenho que habilitar o perl na freeradius/3.0/mods-enabledpasta e modificar o nome do arquivo freeradius/3.0/mods-enabled/perlpara apontá-lo para o meu módulo perl. Como por exemplo:

filename = ${modconfdir}/${.:instance}/dhcp/Options.pm

Mas como faço para referenciar a chamada para perl da maneira correta?

Eu pensei que tinha que habilitar a linha func_post_auth = post_authe freeradius/3.0/mods-enabled/perlcriar uma sub post_authseção no meu módulo perl para lidar com chamadas do Freeradius, mas pelo que posso ver no meu log, recebo o seguinte erro no Freeradius:

(8) perl: perl_embed:: module = /etc/freeradius/3.0/mods-config/perl/dhcp/Options.pm , 
func = post_auth exit status= Undefined subroutine &main::post_auth called.
...
(8)     [perl] = fail
(8)   } # dhcp DHCP-Discover = fail

Então, o que é que eu não estou vendo?

perl freeradius dhcp-server
  • 1 1 respostas
  • 108 Views

1 respostas

  • Voted
  1. Best Answer
    Lasse Michael Mølgaard
    2022-05-17T01:32:19+08:002022-05-17T01:32:19+08:00

    Bati minha cabeça contra a parede algumas vezes, mas pelo menos consegui que o módulo perl funcionasse, embora não esteja completamente onde quero estar, já que o roteamento estático via DHCP não passa do servidor DHCP do Freeradius para o cliente VPN via Strongswan , mas depurar pacotes UDP do servidor DHCP do Freeradius implica que o problema está em outro lugar.

    De qualquer forma aqui está o que eu fiz:

    1. Habilite o módulo perl freeradius/3.0/mods-enablede defina pelo menos as seguintes linhas:
    perl {
      # Perl code location: ("freeradius/3.0/mods-config/dhcp/Options.pm")
      filename = ${modconfdir}/${.:instance}/dhcp/Options.pm
    
      # DHCP module is called during freeradius post_auth
      func_post_auth = post_auth
    }
    
    1. Modificar freeradius/3.0/sites-enabled/dhcp Os locais relevantes são DHCP-Discovere DHCP-Request:
    dhcp DHCP-Discover {
    
            update reply {
                   DHCP-Message-Type = DHCP-Offer
            }
    
            #  The contents here are invented.  Change them!
            update reply {
                    &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
            }
    
            #  Or, allocate IPs from the DHCP pool in SQL. You may need to
            #  set the pool name here if you haven't set it elsewhere.
            update control {
                    &Pool-Name := "vpn_pool"
            }
    
            dhcp_sqlippool
    
            # Call static route generation.
            perl
    
            ok
    }
    
    dhcp DHCP-Request {
    
            # Response packet type. See DHCP-Discover section above.
            update reply {
                   &DHCP-Message-Type = DHCP-Ack
            }
    
            #  The contents here are invented.  Change them!
            update reply {
                    &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
            }
    
            #  Or, allocate IPs from the DHCP pool in SQL. You may need to
            #  set the pool name here if you haven't set it elsewhere.
            update control {
                    &Pool-Name := "vpn_pool"
            }
     
            dhcp_sqlippool
    
            # Call static route generation.
            perl
    
            ok
    }
    
    1. Crie o código perl localizado em freeradius/3.0/mods-config/perl/dhcp/Options.pm:
    use strict;
    use warnings;
    use Data::Dumper;
    use Net::IP;
    
    # Bring the global hashes into the package scope
    our (%RAD_REQUEST, %RAD_REPLY, %RAD_CHECK);
    
    #
    # This the remapping of return values
    #
    use constant {
        RLM_MODULE_REJECT   => 0, # immediately reject the request
        RLM_MODULE_OK       => 2, # the module is OK, continue
        RLM_MODULE_HANDLED  => 3, # the module handled the request, so stop
        RLM_MODULE_INVALID  => 4, # the module considers the request invalid
        RLM_MODULE_USERLOCK => 5, # reject the request (user is locked out)
        RLM_MODULE_NOTFOUND => 6, # user not found
        RLM_MODULE_NOOP     => 7, # module succeeded without doing anything
        RLM_MODULE_UPDATED  => 8, # OK (pairs modified)
        RLM_MODULE_NUMCODES => 9  # How many return codes there are
    };
    
    # Same as src/include/radiusd.h
    use constant    L_DBG=>   1;
    use constant    L_AUTH=>  2;
    use constant    L_INFO=>  3;
    use constant    L_ERR=>   4;
    use constant    L_PROXY=> 5;
    use constant    L_ACCT=>  6;
    
    # Function to handle post_auth
    
    sub post_auth {
    
        # Get VPN Client IP from Freeradius DHCP server.
        my $client_ip = new Net::IP ( $RAD_REQUEST{'DHCP-Requested-IP-Address'} ) or die (Net::IP::Error());
    
        # An example of 2 routing rules sent ('192.168.20.0/24' and '192.168.200.0/24') 
        my @routes = (new Net::IP('192.168.20/24'), new Net::IP('192.168.200/24'));
    
        # Measure how many elements there is in the routes array.
        my $size = @routes;
    
        # Convert client ip into hex code.
        my $client_octets = get_ip_octets ($client_ip->ip(),$client_ip->prefixlen());
    
        # Freeradius want the encoded string start with '0x'
        # followed by the encoded octets as hex.
        my $octet_str = "0x";
    
        for(my $i = 0; $i < $size; $i++)
        {
            # Convert subnet into octets, skipping ending zeroes.
            my $route_octets = get_ip_octets ($routes[$i]->ip(),$routes[$i]->prefixlen());
    
            # Convert network prefix into octets
            my $hex_prefix = sprintf("%02x", $routes[$i]->prefixlen());
    
            # Route is encoded by network octets followed by subnet octets
            $route_octets = $hex_prefix . $route_octets;
    
            # The entire route string is the route octets followed by gateway octets ('the client vpn ip').
            my $route_str = $route_octets . $client_octets;
    
            $octet_str = $octet_str . $route_str;
        }
    
        # Classless static routing (dhcp option 121)
        $RAD_REPLY{'DHCP-Classless-Static-Route'} = $octet_str;
    
        # Microsoft classless static routing (dhcp option 249)
        $RAD_REPLY{'DHCP-Site-specific-25'} = $octet_str;
    
        return RLM_MODULE_OK;
    
    }
    
    sub get_ip_octets {
        # First parameter: Source ip address
        my $sip = $_[0];
    
        # Second parameter: Bitlength of network (aka CIDR notation).
        my $cidr = $_[1];
    
        my @decimals = split('\.', $sip);
        my $index = int($cidr / 8) ;
    
        my $result = '';
        for(my $i = 0; $i < $index; $i++)
        {
            # Convert each number in ip address to hex and format with leading
            # zero in case converted number is less than 16.
            $result = $result . sprintf("%02x", $decimals[$i]);
        }
    
        return $result;
    }
    

    O código perl pode ser ajustado a partir daqui, então a opção 121 ou a opção 249 é enviada dependendo do sistema operacional do cliente.

    Deixo também a possibilidade de tornar o código mais genérico, para que as rotas estáticas possam ser definidas diretamente no arquivo de configuração do Freeradius para o leitor.

    • 0

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Você pode passar usuário/passar para autenticação básica HTTP em parâmetros de URL?

    • 5 respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Verifique se a porta está aberta ou fechada em um servidor Linux?

    • 7 respostas
  • Marko Smith

    Como automatizar o login SSH com senha?

    • 10 respostas
  • Marko Smith

    Como posso dizer ao Git para Windows onde encontrar minha chave RSA privada?

    • 30 respostas
  • Marko Smith

    Qual é o nome de usuário/senha de superusuário padrão para postgres após uma nova instalação?

    • 5 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    kernel O scp pode copiar diretórios recursivamente? 2011-04-29 20:24:45 +0800 CST
  • Martin Hope
    Robert ssh retorna "Proprietário incorreto ou permissões em ~/.ssh/config" 2011-03-30 10:15:48 +0800 CST
  • Martin Hope
    Eonil Como automatizar o login SSH com senha? 2011-03-02 03:07:12 +0800 CST
  • Martin Hope
    gunwin Como lidar com um servidor comprometido? 2011-01-03 13:31:27 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve