Sign inSign up

wbh16/eduroam

By wbh16

Updated almost 2 years ago

Servidor FreeRADIUS para Eduroam com integração AD via Kerberos/Samba, contêiner Docker-compose

Image
Security
0

1.9K

wbh16/eduroam repository overview

Descrição do Projeto no Docker Hub
Nome do Projeto: RADIUS Eduroam
Descrição

Este projeto implementa um servidor FreeRADIUS configurado para autenticar usuários na rede Eduroam. Integra-se com o Active Directory via Kerberos e Samba, sendo contêinerizado com Docker para facilitar a implantação e a gestão. Inclui scripts automatizados para geração de certificados, persistência de logs e administração simplificada.

Estrutura do Projeto
  1. Compilando Imagem
# Use a imagem base do Debian
FROM debian:11

# Contato do mantenedor:
LABEL maintainer="[email protected]"

# Definir o frontend não interativo para evitar prompts durante a instalação
ENV DEBIAN_FRONTEND=noninteractive

# Atualize o sistema e instale as dependências necessárias
RUN apt-get update && apt-get upgrade -y && apt-get dist-upgrade -y && apt-get autoremove -y && apt-get autoclean -y

# Instalar ntp para configuração de horário
RUN apt-get install -y ntp

# Instalar Kerberos
RUN apt-get install -y krb5-config libpam-krb5 krb5-user krb5-kdc

# Instalar Samba, smbclient, winbind e expect
RUN apt-get install -y samba smbclient winbind

# Instalar FreeRADIUS e suas dependências
RUN apt-get install -y freeradius freeradius-ldap freeradius-utils libfreeradius-dev

# Instalar tzdata e configurar o fuso horário
RUN apt-get install -y tzdata && \
    ln -sf /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime && \
    echo "America/Sao_Paulo" > /etc/timezone

# Adicionar o usuário freerad ao grupo winbindd_priv
RUN usermod -a -G winbindd_priv freerad

# Configurar permissões
RUN chgrp winbindd_priv /var/lib/samba/winbindd_privileged/

# Adicionar a configuração TTL
RUN echo "net.ipv4.ip_default_ttl = 128" >> /etc/sysctl.conf

# Copiar o script de entrada
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Expor a porta do FreeRADIUS
EXPOSE 1812/udp 1813/udp

# Comando para iniciar os serviços
ENTRYPOINT ["/entrypoint.sh"]

1.1 Como usar:

  • Certifique-se de que o Dockerfile esteja atualizado conforme acima.
  • Construa a imagem Docker:
docker-compose build
  1. Arquivo do docker-compose
version: '3.8'
networks:
  vlan_rede_admin:
    external: true
volumes:
  eduroam_freeradius_logs:
services:
  freeradius:
    build: .
    image: wbh16/eduroam             # Nome e tag da imagem que será gerada
    container_name: iba-eduroam      # nome do container
    hostname: iba-eduroam
    networks:
      vlan_rede_admin:
        ipv4_address: 172.17.80.22
    cap_add:
      - ALL
    ports:
      - "1812:1812/udp"
      - "1813:1813/udp"
    volumes:
      - ./configs/freeradius:/etc/freeradius/3.0
      - ./configs/system/ntp.conf:/etc/ntp.conf
      - ./configs/system/smb.conf:/etc/samba/smb.conf
      - eduroam_freeradius_logs:/var/log/freeradius # Volume para persistir os logs
    environment:
      KERBEROS_REALM: CEFETES.BR  # Substitua pelo seu domínio Kerberos
      TZ: America/Sao_Paulo       # Fuso horário

      # Valores para gerar certificado
      C: "BR"
      ST: "ES"
      L: "Ibatiba"
      O: "IFES"
      OU: "CTI"
      CN: "cefetes.br"
      emailAddress: "[email protected]"
      #
    restart: always
  1. Arquivo entrypoint.sh
#!/bin/bash

# Ajustar permissões para os arquivos montados
chown -R freerad:freerad /etc/freeradius/3.0
chmod -R 755 /etc/freeradius/3.0

# Configurar permissões específicas para o arquivo authorize
chown freerad:freerad /etc/freeradius/3.0/mods-config/files/authorize
chmod 644 /etc/freeradius/3.0/mods-config/files/authorize

# Iniciar ntp, samba e winbind
service ntp start

# Reiniciar serviços
service smbd restart
service winbind restart

# Iniciar o FreeRADIUS em modo depuração
freeradius -X
  1. Arquivo de inicialização
#!/bin/bash

# Nome do contêiner e outras variáveis
CONTAINER_NAME=$(grep 'container_name:' docker-compose.yml | awk '{print $2}')

# Função para iniciar o contêiner
iniciar() {
    # Verificar se o contêiner está em execução
    if [ $(docker ps -q -f name=${CONTAINER_NAME} | wc -l) -eq 0 ]; then
        echo "Contêiner não está em execução. Iniciando o contêiner..."
        docker-compose up -d --build

        echo "Aguardando inicio do Container..."
        sleep 10
    else
        echo "Contêiner já está em execução."
        docker-compose up -d
    fi

    KERBEROS_REALM=$(docker exec -it ${CONTAINER_NAME} printenv KERBEROS_REALM | tr -d '\r')

    echo "Aguardando o contêiner verificar o dominio..."
    # Verificar se a junção ao domínio foi bem-sucedida
    JOIN_RESULT=$(docker exec -it ${CONTAINER_NAME} wbinfo -t 2>&1)

    if echo "${JOIN_RESULT}" | grep -q "succeeded"; then
        echo "Contêiner está no domínio!"
    else
        # Solicitar o usuário:
        echo "Digite um usuário com permissão de adicionar máquinas ao domínio:"
        read DOMAIN_USER

        # Configurar Kerberos
        docker exec -it ${CONTAINER_NAME} bash -c "
        echo \"[libdefaults]
            default_realm = ${KERBEROS_REALM}
        [realms]
            ${KERBEROS_REALM} = {
                kdc = kdc.${KERBEROS_REALM}
                admin_server = admin.${KERBEROS_REALM}
            }
        [domain_realm]
            .${KERBEROS_REALM} = ${KERBEROS_REALM}
            ${KERBEROS_REALM} = ${KERBEROS_REALM}\" > /etc/krb5.conf
        "

        # Adicionar o contêiner ao domínio
        echo "Adicionando o contêiner ao domínio, pode demorar!"
        docker exec -it ${CONTAINER_NAME} net ads join -U ${DOMAIN_USER}

        # Reiniciar o contêiner para garantir que todas as configurações sejam aplicadas
        docker-compose restart
        echo "Aguardando inicio do Container..."
        sleep 10
    fi

    # Verificar o status do Winbind
    echo "Verificando o status do Winbind..."
    docker exec -it ${CONTAINER_NAME} wbinfo -t
}

# Função para gerar certificado
gerar_certificado() {
    echo "Gerando certificado..."

    CERTS_DIR="/etc/freeradius/3.0/certs"
    MONTH_YEAR=$(date +%m_%Y)
    NEW_CERTS_DIR="${CERTS_DIR}/certificado_${MONTH_YEAR}"

    # Verificar e criar diretório se não existir
    if docker exec -it ${CONTAINER_NAME} test -d ${NEW_CERTS_DIR}; then
        echo "Diretório ${NEW_CERTS_DIR} já existe. Por favor, remova ou escolha um mês/ano diferente."
        echo " Para remover: docker exec -it ${CONTAINER_NAME} rm -rf ${NEW_CERTS_DIR}"
        exit 1
    else
        docker exec -it ${CONTAINER_NAME} bash -c "mkdir -p ${NEW_CERTS_DIR}"
    fi

    CA_KEY="${NEW_CERTS_DIR}/ca.key"
    CA_CRT="${NEW_CERTS_DIR}/ca.crt"
    SERVER_KEY="${NEW_CERTS_DIR}/wifi_${MONTH_YEAR}.key"
    SERVER_CSR="${NEW_CERTS_DIR}/wifi_${MONTH_YEAR}.csr"
    SERVER_CRT="${NEW_CERTS_DIR}/wifi_${MONTH_YEAR}.crt"
    ALL_CRT="${NEW_CERTS_DIR}/all_${MONTH_YEAR}.crt"
    ALL_KEY="${NEW_CERTS_DIR}/all_${MONTH_YEAR}.key"
    OPENSSL_CONF="${NEW_CERTS_DIR}/openssl.cnf"

    # Solicitar a senha uma vez
    echo "Digite a senha para as chaves do certificado:"
    read -s CERT_PASSWORD

    # Obter valores das variáveis de ambiente
    C=$(docker exec -it ${CONTAINER_NAME} printenv C | tr -d '\r')
    ST=$(docker exec -it ${CONTAINER_NAME} printenv ST | tr -d '\r')
    L=$(docker exec -it ${CONTAINER_NAME} printenv L | tr -d '\r')
    O=$(docker exec -it ${CONTAINER_NAME} printenv O | tr -d '\r')
    OU=$(docker exec -it ${CONTAINER_NAME} printenv OU | tr -d '\r')
    CN=$(docker exec -it ${CONTAINER_NAME} printenv CN | tr -d '\r')
    emailAddress=$(docker exec -it ${CONTAINER_NAME} printenv emailAddress | tr -d '\r')

    # Criar o arquivo openssl.cnf
    echo "Criando o arquivo openssl.cnf..."
    docker exec -it ${CONTAINER_NAME} bash -c "echo '[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = req_distinguished_name
prompt = no

[ req_distinguished_name ]
C = ${C}
ST = ${ST}
L = ${L}
O = ${O}
OU = ${OU}
CN = ${CN}
emailAddress = ${emailAddress}
' > ${OPENSSL_CONF}"

    # Gerar a chave e o certificado da CA
    echo "Gerando a chave RSA 2048 da CA..."
    docker exec -it ${CONTAINER_NAME} bash -c "openssl genrsa -des3 -passout pass:${CERT_PASSWORD} -out ${CA_KEY} 2048"
    echo "Gerando o certificado X509 da CA..."
    docker exec -it ${CONTAINER_NAME} bash -c "openssl req -new -x509 -days 3650 -key ${CA_KEY} -out ${CA_CRT} -config ${OPENSSL_CONF} -passin pass:${CERT_PASSWORD}"

    # Gerar a chave privada do servidor e o CSR
    echo "Gerando a chave privada do servidor..."
    docker exec -it ${CONTAINER_NAME} bash -c "openssl genrsa -des3 -passout pass:${CERT_PASSWORD} -out ${SERVER_KEY} 2048"
    echo "Gerando o CSR (Certificate Signing Request)..."
    docker exec -it ${CONTAINER_NAME} bash -c "openssl req -new -key ${SERVER_KEY} -out ${SERVER_CSR} -config ${OPENSSL_CONF} -passin pass:${CERT_PASSWORD}"
    echo "Gerando o certificado público assinado pela CA..."
    docker exec -it ${CONTAINER_NAME} bash -c "openssl x509 -req -days 3650 -in ${SERVER_CSR} -CA ${CA_CRT} -CAkey ${CA_KEY} -set_serial 01 -out ${SERVER_CRT} -passin pass:${CERT_PASSWORD}"

    # Concatenar os certificados
    echo "Concatenando os certificados gerados..."
    docker exec -it ${CONTAINER_NAME} bash -c "cat ${CA_CRT} ${SERVER_CRT} > ${ALL_CRT}"
    docker exec -it ${CONTAINER_NAME} bash -c "cat ${CA_KEY} ${SERVER_KEY} > ${ALL_KEY}"

    # Configurar permissões
    echo "Configurando permissões..."
    docker exec -it ${CONTAINER_NAME} chown freerad:freerad ${CERTS_DIR} -R
}

# Função para limpeza
limpeza() {
    echo "Aviso: Este comando pode apagar recursos úteis de outros contêineres que estão parados."
    echo "Esta ação irá parar e remover o contêiner e imagem relacionados ao projeto atual."

    read -p "Deseja continuar? (y/n): " choice
    if [[ "$choice" != "y" ]]; then
        echo "Ação de limpeza cancelada."
        exit 0
    fi

    echo "Limpando contêiner e imagens relacionadas ao projeto atual..."

    # Parar e remover o contêiner
    docker-compose down

    # Remover a imagem Docker relacionada ao projeto atual
    IMAGE_NAME=$(docker images | grep $(grep 'image:' docker-compose.yml | awk '{print $2}') | awk '{print $3}')
    if [[ ! -z "$IMAGE_NAME" ]]; then
        docker rmi -f "$IMAGE_NAME"
    fi

    echo "Limpeza concluída."
}

logs() {
    echo "Exibindo logs do FreeRADIUS..."
    docker exec -it ${CONTAINER_NAME} tail -f /var/log/freeradius/radius.log
}

# Verificar argumento passado para o script
case "$1" in
    iniciar)
        iniciar
        ;;
    gerar_certificado)
        gerar_certificado
        ;;
    limpeza)
        limpeza
        ;;
    logs)
        logs
        ;;
    *)
        echo "Uso: $0 {iniciar|gerar_certificado|limpeza|logs}"
        exit 1
esac

5.1 Testando autenticação no AD

Para verificar se a autenticação ntlm_auth está funcionando execute:
/usr/bin/ntlm_auth --domain=CEFETES.BR --username=1452723
/usr/b
in/ntlm_auth --request-nt-key --domain=CEFETES.BR --username=1452723
Password:[digite a senha]

5.2 Testar o Samba

testparm

5.3 Rodar o Winbind em Modo Depuração

winbindd -SFd5

5.4 Em Outro Terminal Rode o FreeRADIUS em Modo Depuração

systemctl stop freeradius
freeradius -X

5.5 Num Terceiro Terminal Rode o Comando de Teste

radtest -t mschap user1 usersenha 127.0.0.1 0 senha_equipamento_cliente

5.6 Testando a Autenticação com o FreeRADIUS

radtest -t mschap <usuario> <senha> <endereco_ip_servidor> <porta> <senha_equipamento>

Exemplo prático:

radtest -t mschap john_doe "mypassword" 172.17.80.246 1 mysecretpassword
Conclusão

Este projeto RADIUS Eduroam oferece uma solução robusta e segura para autenticação de usuários em redes educacionais, garantindo operação eficiente e fácil administração, alinhada com os padrões de segurança exigidos pela rede Eduroam.

Tag summary

Content type

Image

Digest

sha256:ccdc4e1c5

Size

190.9 MB

Last updated

about 2 years ago

docker pull wbh16/eduroam