FreeRadius – Guia rápido

Saudações.

Esse tutorial é um guia rápido de instalação e uso do Freeradius em Docker.

É sempre nostálgico para mim trabalhar com ele, foi um dos primeiros softwares que documentei no VivaoLinux (2005) e me rendeu as primeiras consultorias da minha carreira.

Pré-requisitos (constam em outros artigos aqui do blog):

  • Instalação do Linux (Debian);
  • Internet no servidor (sua VPS ou host);
  • Docker CE instalado;

1 – Sobre FreeRadius

O FreeRadius é um sistema especializado no protocolo RADIUS (Remote Authentication Dial-In User Service), provendo um framework completo de tratamento de requisições e respostas.

É a plataforma mais utilizada no mundo para AAA (Authentication, Authorization, and Accounting).

1.1 – Conceitos fundamentais

O FreeRadius possui dois serviços internos:

  • Autenticação e Autorização: Normalmente escuta na porta UDP 1812, a porta TCP também é suportada mas pouco utilizada;
  • Contabilidade: Normalmente escuta na porta UDP 1813.

O AAA funciona com a seguinte divisão de tarefas:

  • Autenticação (Authentication): Foco em identificar o usuário que deseja utilizar um recurso de rede, é MUITO importante entender que autenticar não é autorizar, no RADIUS autenticar é garantir que que a identidade de um usuário é verdadeira (Access-Request):
    • João é João porque apresentou o nome completo (user-name) e senha (password);
  • Autorização (Authorization): Uma vez identificado o usuário como legítimo (devidamente cadastrado), essa etapa visa verificar se ele pode ou não usar o recurso desejado:
    • João deseja usar o WIFI (rede “funcionarios”), autorizado (Access-Accept);
    • João deseja usar o WIFI (rede “gerencia”), acesso negado (Access-Reject);
  • Contabilidade (Accounting): Parte dedicada a registrar o consumo de recursos dos usuários:
    • Start: Registra o inicio do uso de um recurso;
    • Interim-Update: Atualiza o uso de recursos;
    • Stop: Registra o fim do uso dos recursos.

Embora o RADIUS seja empregado majoritariamente para autenticação de conexões PPPoE, VPN e WIFI, ele pode ser usado para qualquer finalidade de controle AAA.

1.2 – Agentes RADIUS

Cada equipamento participa do framework RADIUS como um agente específico:

  • NAS (Network Access Service): É o software ou equipamento que atende o usuário final. O NAS ele é o cliente RADIUS, tudo que o usuário final pedir será convertido no pacote RADIUS e enviado ao servidor RADIUS.
  • Servidor RADIUS: É onde o FreeRadius opera, ele é um agente passivo esperando pedidos de autenticação para responder, o cliente (NAS) precisa ser autorizado por meio do IP de origem e da “secret“;
  • Agente COA: É um software responsável por perceber mudanças na situação do usuário ou da sessão de contabilidade e enviar ordens ao NAS para mudar o tratamento ao usuário:
    • Desconectar: Caso ele seja desativado ou exceda o uso de recursos;
    • Reclassificação: Caso o usuário precise receber mais ou menos recursos, como velocidade de navegação.
  • Servidor COA: É um servidor especial que escuta pedidos no NAS, ele autentica se pedidos COA são legítimos por meio de autenticação “secret“.

Visão geral:

Em alguns casos especiais, existe o emprego do servidor RADIUS como Proxy RADIUS. Essa modalidade é usada para pre-processamento de requisições antes do servidor final:

  • Switch: Faz separação por REALM (domínio), exemplo:
    • joao vai para o servidor A;
    • maria@intranet.br vai para o servidor B;
    • jose%tech vai para o servidor C;
  • Fail-over: Quando o servidor X para de responder, encaminha para o servidor Y.

2 – Preparativos

Você deve ter o Docker instalado no servidor Linux (Tutorial de Docker).

Atualizar seu sistema Debian:

Bash
# Atualizar sistema local
apt -y update;
apt -y upgrade;
apt -y dist-upgrade;
apt -y autoremove;

Ferramentas que vamos precisar para testes:

Bash
# Instalar ferramentas para testar o servidor RADIUS:
apt-get -y install freeradius-utils;

Rede Docker onde vamos rodar os containers de FreeRadius:

Bash
# Rede de containers FreeRadius
docker network create radius \
    -d bridge \
    -o com.docker.network.bridge.name=br-radius \
    -o com.docker.network.driver.mtu=1500 \
    -o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
    --subnet 10.177.177.0/24 \
    --gateway 10.177.177.254;

3 – FreeRadius coringa

O primeiro contato com um servidor FreeRadius é a montagem de um servidor aberto que autoriza todo mundo, normalmente apelidado de “RADIUS Coringa“. Eu prefiro chamar de “FreeRadius aberto” e criei um container “freeradius-open“.

Esse servidor é MUITO desejado quando o verdadeiro servidor sai do ar e a rede fica 100% parada.

Criando container no Docker (modo rápido, secret padrão tulipa):

Bash
#!/bin/sh

# Volume (para logs)
    mkdir -p /storage/freeradius-open;

# Rodar container
    docker rm -f freeradius-open 2>/dev/null;
    docker run -d \
        --name=freeradius-open --hostname freeradius-open.intranet.br \
        --restart=always \
        --read-only \
        \
        -p 1812:1812/tcp -p 1813:1813/tcp \
        -p 1812:1812/udp -p 1813:1813/udp \
        \
        --tmpfs /run:rw,size=2m \
        -v /storage/freeradius-open:/data \
        \
        tmsoftbrasil/freeradius-open:latest;

Exemplo mais completo do mesmo container acima usando a rede “radius” e personalizando a secret na variável FREERADIUS_SECRET (usar tulipa):

Bash
#!/bin/sh

# Volume (para logs)
    mkdir -p /storage/freeradius-open;

# Rodar container
    docker rm -f freeradius-open 2>/dev/null;
    docker run -d \
        --name=freeradius-open --hostname freeradius-open.intranet.br \
        --cpus=1.0 --memory=128m --memory-swap=128m \
        --restart=always \
        --network radius \
        --ip=10.177.177.20 \
        --mac-address "00:10:00:00:00:02" \
        \
        -p 1812:1812/tcp -p 1813:1813/tcp \
        -p 1812:1812/udp -p 1813:1813/udp \
        \
        -e FREERADIUS_SECRET=tulipa \
        \
        --read-only \
        --tmpfs /run:rw,size=2m \
        -v /storage/freeradius-open:/data \
        \
        tmsoftbrasil/freeradius-open:latest;

Acompanhando os logs:

Bash
# Analisar logs em tempo real:
tail -f /storage/freeradius-open/logs/radius.log;
   # Mon Mar .. : Auth: (13) Login OK: [ping/pass] (from client LOCALHOSTv4 port 0)
   # Mon Mar .. : Auth: (14) Login OK: [ping/pass] (from client LOCALHOSTv4 port 0)
   # Mon Mar .. : Auth: (15) Login OK: [ping/pass] (from client LOCALHOSTv4 port 0)
   # Mon Mar .. : Auth: (16) Login OK: [ping/pass] (from client LOCALHOSTv4 port 0)

Testando: Envie para o IP do container ou para o IP do servidor (HOST):

Bash
# IP do servidor
IP="45.255.128.2";

# Porta
AUTH_PORT="1812";

# Secret (padrao)
SECRET="tulipa";

radtest teste 123456 $IP:$AUTH_PORT 0 $SECRET;
    # Sent Access-Request Id 219 from 0.0.0.0:27534 to 45.255.128.2:1812 length 75
    # 	User-Name = "teste"
    # 	User-Password = "123456"
    # 	NAS-IP-Address = 45.255.128.90
    # 	NAS-Port = 0
    # 	Message-Authenticator = 0x00
    # 	Cleartext-Password = "123456"
    # Received Access-Accept Id 219
    #      from 45.255.128.2:1812 to 45.255.128.90:27534 length 38
    # 	Message-Authenticator = 0xecf699cb8e7837bfb48c2090560e8c94

4 – Código-fonte

O código-fonte do projeto original é necessário para obter os arquivos de configuração padrão para os próximos capítulos.

Bash
# Obter codigo do projeto vai Github
#PROJECT_VERSION="master";
PROJECT_VERSION="v3.2.x";

# Diretorio local
mkdir -p /usr/src/freeradius;
cd /usr/src/freeradius;

# Clonar fontes (download):
git clone \
    --branch $PROJECT_VERSION \
    --single-branch https://github.com/FreeRADIUS/freeradius-server.git . ;

5 – FreeRadius com MariaDB

Evoluindo na dificuldade, montar um servidor RADIUS com dados de usuários e contabilidade no MariaDB (antigo MySQL). Esse é o tipo mais mediocre de servidor que existe e quase sempre resulta em crises de I/O do banco de dados por conta da estrutura mal feita e entregue por padrão na configuração do FreeRadius.

5.1 – Preparando banco de dados

Instalar MariaDB Client para conectar partindo do HOST:

Bash
# Instalar cliente mysql/mariadb, comando final: mariadb
apt-get -y install mariadb-client;

Criando o container do MariaDB com nome “freeradius-mariadb“:

Bash
# Diretório para o volume do MariaDB:
mkdir -p /storage/freeradius-mariadb;

# Parar atual (para update de imagem)
    docker stop freeradius-mariadb 2>/dev/null;
    docker rm   freeradius-mariadb 2>/dev/null;

# Baixar imagem atualizada
    docker pull mariadb:latest;

# Rodar/ranovar mariadb:
docker run \
    -d \
    --name freeradius-mariadb \
    --hostname freeradius-mariadb.intranet.br \
    --cpus=4.0 --memory=2g --memory-swap=2g --shm-size=1g \
    --restart=always \
    \
    --network radius \
    --ip=10.177.177.251 \
    --mac-address "00:10:00:00:f2:51" \
    \
    -e MYSQL_ROOT_PASSWORD=tulipasql \
    -e MYSQL_DATABASE=freeradius \
    -e MYSQL_USER=freeradius \
    -e MYSQL_PASSWORD=tulipasql \
    \
    --tmpfs /run:rw,noexec,nosuid,size=8m \
    --tmpfs /run/mysqld:rw,noexec,nosuid,size=64m \
    --tmpfs /tmp:rw,noexec,nosuid,size=64m \
    \
    -v /storage/freeradius-mariadb:/var/lib/mysql \
    \
    mariadb:latest;

Acessando e administrando o banco:

Bash
# Acesso como root (administrador): root / tulipasql
mariadb -h 10.177.177.251 -u root       -ptulipasql;

# Acesso como freeradius (cliente comum do banco)
mariadb -h 10.177.177.251 -u freeradius -ptulipasql freeradius;

# Comandos comuns:
# SHOW DATABASES;
# USE freeradius;
# SHOW TABLES;
# DESCRIBE nome_da_tabela;
#
# Comando para sair do shell sql:
# exit

5.2 – Criando tabelas no MariaDB

Instalando esquema padrão de tables para MySQL:

Bash
# Caminho do esquema padrao no codigo-fonte do projeto:
SRC="/usr/src/freeradius";
SCH_MAIN="$SRC/raddb/mods-config/sql/main/mysql/schema.sql";
SCH_CUI="$SRC/raddb/mods-config/sql/cui/mysql/schema.sql";
SCH_POOL="$SRC/raddb/mods-config/sql/ippool/mysql/schema.sql";
SCH_DHCP="$SRC/raddb/mods-config/sql/ippool-dhcp/mysql/schema.sql";

# Aplicar no banco de dados 'freeradius':
cat $SCH_MAIN | mariadb -h 10.177.177.251 -u root -ptulipasql freeradius;
cat $SCH_CUI  | mariadb -h 10.177.177.251 -u root -ptulipasql freeradius;
cat $SCH_POOL | mariadb -h 10.177.177.251 -u root -ptulipasql freeradius;
cat $SCH_DHCP | mariadb -h 10.177.177.251 -u root -ptulipasql freeradius;

Conferindo tabelas:

Bash
# Listar tabelas do banco 'freeradius':
mariadb -h 10.177.177.251 -u freeradius -ptulipasql freeradius -e "SHOW TABLES";

# Retorno desejado:
    # +----------------------+
    # | Tables_in_freeradius |
    # +----------------------+
    # | cui                  |
    # | dhcpippool           |
    # | nas                  |
    # | nasreload            |
    # | radacct              |
    # | radcheck             |
    # | radgroupcheck        |
    # | radgroupreply        |
    # | radippool            |
    # | radpostauth          |
    # | radreply             |
    # | radusergroup         |
    # +----------------------+

5.3 – Cadastrando concentradores (NAS)

O servidor RADIUS responderá somente a pedidos vindo de equipamentos conhecidos, os NAS (concentradores PPPoE, roteadores hotspot, WIFI, etc).

Bash
# Comando base para executar SQL:
_sql(){
    echo;
    echo "# SQL QUERY: $1";
    mariadb -h 10.177.177.251 -u freeradius -ptulipasql freeradius -e "$1";
    echo;
};

# Variaveis para acelerar comandos SQL
IN="INSERT INTO nas(nasname, shortname, secret) VALUES";

# Cadastrar concentrador GLOBALv4 para permitir todos os endereços IPv4
_sql "DELETE FROM nas WHERE shotname = 'GLOBALv4';";
_sql "$IN ('0.0.0.0/0', 'GLOBALv4', 'tulipa');";

# Cadastrar concentrador GLOBALv6 para permitir todos os endereços IPv6
_sql "DELETE FROM nas WHERE shotname = 'GLOBALv6';";
_sql "$IN ('::/0', 'GLOBALv6', 'tulipa');";

# Conferindo:
_sql "SELECT * FROM nas;";

5.4 – Criando usuários

Preencher tabelas com objetos de teste.

Usuário básico para teste simples “teste” (usado pelo ping healthcheck):

Bash
# Comando base para executar SQL:
_sql(){
    echo;
    echo "# SQL QUERY: $1";
    mariadb -h 10.177.177.251 -u freeradius -ptulipasql freeradius -e "$1";
    echo;
};

# Variaveis para acelerar comandos SQL
IC="INSERT INTO radcheck(username, attribute, op, value) VALUES";
IR="INSERT INTO radreply(username, attribute, op, value) VALUES";

#------------------------------------------------ login: teste
# Remover usuario de teste 'teste':
_sql "DELETE FROM radcheck WHERE username = 'teste';"
_sql "DELETE FROM radreply WHERE username = 'teste';"

# - auth:
_sql "$IC ('teste', 'Cleartext-Password', ':=', '123456')";

# - reply:
_sql "$IR ('teste', 'Acct-Interim-Interval',       '=', '60')";

# Conferindo:
_sql "SELECT * FROM radcheck WHERE username = 'teste';";
_sql "SELECT * FROM radreply WHERE username = 'teste';";

Usuário “mk01“:

Bash
# Comando base para executar SQL:
_sql(){
    echo;
    echo "# SQL QUERY: $1";
    mariadb -h 10.177.177.251 -u freeradius -ptulipasql freeradius -e "$1";
    echo;
};

# Variaveis para acelerar comandos SQL
IC="INSERT INTO radcheck(username, attribute, op, value) VALUES";
IR="INSERT INTO radreply(username, attribute, op, value) VALUES";

#------------------------------------------------ login: mk01
# Remover usuario de teste 'mk01':
_sql "DELETE FROM radcheck WHERE username = 'mk01';"
_sql "DELETE FROM radreply WHERE username = 'mk01';"

# - auth:
_sql "$IC ('mk01', 'Cleartext-Password', ':=', '123456')";
_sql "$IC ('mk01', 'Simultaneous-Use',   ':=', '1')";

# - reply:
_sql "$IR ('mk01', 'RP-Downstream-Speed-Limit',   '=', '5128')";
_sql "$IR ('mk01', 'RP-Upstream-Speed-Limit',     '=', '2048')";
_sql "$IR ('mk01', 'Mikrotik-Rate-Limit',         '=', '2048k/5128k')";
_sql "$IR ('mk01', 'Mikrotik-Delegated-IPv6-Pool','=', '2001:db8:baba:baba::/64')";
_sql "$IR ('mk01', 'Acct-Interim-Interval',       '=', '300')";
_sql "$IR ('mk01', 'Framed-IP-Address',           '=', '10.80.80.2')";
_sql "$IR ('mk01', 'Framed-IPv6-Address',         '=', '2001:db8:beba:cafe::9999')";
_sql "$IR ('mk01', 'Framed-IPv6-Prefix',          '=', '2001:db8:beba:fada::/64')";
_sql "$IR ('mk01', 'Delegated-IPv6-Prefix',       '=', '2001:db8:beba:c0ca::/64')";
_sql "$IR ('mk01', 'Framed-IPv6-Route',           '=', '2001:db8:beba:fafa::/64')";

# Conferindo:
_sql "SELECT * FROM radcheck WHERE username = 'mk01';";
_sql "SELECT * FROM radreply WHERE username = 'mk01';";

5.5 – Criando container FreeRadius com MariaDB

Agora é hora de colocar o FreeRadius trabalhar baseado nos dados que constam no banco MariaDB:

Bash
# Volume
    mkdir -p /storage/freeradius-server;

# Rodar container
	echo "# Iniciando container...";
    docker rm -f freeradius-server 2>/dev/null;
    docker run \
        -d \
        -h freeradius-server \
        --name=freeradius-server \
        --restart=always \
        --network radius \
        --ip=10.177.177.40 \
        --mac-address "00:10:00:00:0a:04" \
        \
        --memory=1g --memory-swap=1g \
        --sysctl net.core.somaxconn=8192 \
        \
        -p 1812:1812/tcp -p 1813:1813/tcp \
        -p 1812:1812/udp -p 1813:1813/udp \
        \
        --read-only \
        --tmpfs /run:rw,size=8m \
        -v /storage/freeradius-server:/data \
        \
        -e MARIADB_HOST=freeradius-mariadb \
        -e MARIADB_USER=freeradius \
        -e MARIADB_PASS=tulipasql \
        -e MARIADB_NAME=freeradius \
        \
        -e FREERADIUS_TEST_USER=teste \
        -e FREERADIUS_TEST_PASSWORD=123456 \
        -e FREERADIUS_TEST_SECRET=tulipa \
        \
        tmsoftbrasil/freeradius-server-mariadb:latest;

5.6 – Testando o FreeRadius com MariaDB

Os usuários e senhas precisam estar cadastrados no MariaDB (capítulo 5.4).

Bash
# IP do servidor
IP="10.177.177.40";

# Porta
AUTH_PORT="1812";

# Secret (padrao)
SECRET="tulipa";

radtest teste 123456 $IP:$AUTH_PORT 0 $SECRET;
    # Sent Access-Request Id 20 from 0.0.0.0:23987 to 10.177.177.40:1812 length 75
    # 	User-Name = "teste"
    # 	User-Password = "123456"
    # 	NAS-IP-Address = 191.37.79.225
    # 	NAS-Port = 0
    # 	Message-Authenticator = 0x00
    # 	Cleartext-Password = "123456"
    # Received Access-Accept Id 20
    #      from 10.177.177.40:1812 to 10.177.177.254:23987 length 44
    # 	Message-Authenticator = 0xb9815e1ab87ed55b5228bb0e08233252
    # 	Acct-Interim-Interval = 60

6 – FreeRadius com PostgreSQL

O PG é um banco melhor para o FreeRADIUS, se bem operado.

6.1 – Preparando banco de dados

Instalar PSQL (Postgre Client) para conectar partindo do HOST:

Bash
apt-get -y install postgresql-client;

Criando o container do Postgres com nome “freeradius-postgres“:

Bash
# Diretório para o volume do Postgres:
mkdir -p        /storage/freeradius-postgres;
chown -R 999:999 /storage/freeradius-postgres;

# Parar atual (para update de imagem)
    docker stop freeradius-postgres 2>/dev/null;
    docker rm   freeradius-postgres 2>/dev/null;

# Baixar imagem atualizada
    docker pull pgvector/pgvector:pg18-trixie;

# Rodar/renovar postgres:
    docker run \
    		-d \
    		--name freeradius-postgres \
    		--hostname freeradius-postgres.intranet.br \
        --cpus=4.0 --memory=2g --memory-swap=2g --shm-size=1g \
        --restart=always \
        \
        --network radius \
        --ip=10.177.177.252 \
        --mac-address "00:10:00:00:f2:52" \
    		\
        -e POSTGRES_USER=postgres \
        -e POSTGRES_PASSWORD=tulipasql \
        -e POSTGRES_DB=freeradius \
        -e PGDATA=/var/lib/postgresql/data/pgdata \
    		\
        --tmpfs /run:rw,noexec,nosuid,size=64m \
        --tmpfs /tmp:rw,noexec,nosuid,size=64m \
    		\
    		-v /storage/freeradius-mariadb:/var/lib/mysql \
    		\
        --health-cmd="pg_isready -U postgres" \
        --health-interval=15s \
        --health-timeout=5s \
        --health-retries=4 \
        \
        \
        --entrypoint "docker-entrypoint.sh" \
        \
    		pgvector/pgvector:pg18-trixie \
            postgres \
                --max_connections=8192 \
                --wal_level=minimal \
                --max_wal_senders=0 \
                --port=5432;

Acessando e administrando o banco:

Bash
# Acesso como root (no PG o root e' o usuario postgres)
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres;

# Comandos comuns:
# Listar bancos de dados.:  \l
# Conectar a um banco....:  \c freeradius
# Exibir tabelas do banco:  \dt
# Sair do terminal psql...: \q

6.3 – Criando usuário no PG para o FreeRadius

Precisamos criar o usuário freeradius senha tulipasql para o banco freeradius dentro do Postgres. Primeiro, entre como administrador.

Bash
# Acesso como administrador
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres;

Sem seguida, garantir existência do banco e do acesso de usuário freeradius:

x

x

x

x

x

Bash
# Acesso como root (no PG o root e' o usuario postgres)
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres;

# Acesso como freeradius
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U freeradius -d freeradius;

# Comandos comuns:
# Listar bancos de dados.:  \l
# Conectar a um banco....:  \c freeradius
# Exibir tabelas do banco:  \dt
# Sair do terminal psql...: \q

6.2 – Criando tabelas no PG

Instalando esquema padrão de tables para PostgreSQL:

Bash
# Caminho do esquema padrao no codigo-fonte do projeto:
SRC="/usr/src/freeradius";
SCH_MAIN="$SRC/raddb/mods-config/sql/main/postgresql/schema.sql";
SCH_CUI="$SRC/raddb/mods-config/sql/cui/postgresql/schema.sql";
SCH_POOL="$SRC/raddb/mods-config/sql/ippool/postgresql/schema.sql";
SCH_DHCP="$SRC/raddb/mods-config/sql/ippool-dhcp/postgresql/schema.sql";

# Aplicar no banco de dados 'freeradius':
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres -d freeradius -f $SCH_MAIN;
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres -d freeradius -f $SCH_CUI;
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres -d freeradius -f $SCH_POOL;
PGPASSWORD='tulipasql' psql -h 10.177.177.252 -U postgres -d freeradius -f $SCH_DHCP;

6.3 – Cadastrando concentradores (NAS)

Cadastrando equipamentos conhecidos (concentradores PPPoE, roteadores hotspot, WIFI, etc):

Bash
# Comando base para executar SQL:
_sql(){
    echo;
    echo "# SQL QUERY: $1";
    PGPASSWORD='tulipasql' \
        psql -h 10.177.177.252 -U postgres -d freeradius -c "$1";
    echo;
};

# Variaveis para acelerar comandos SQL
IN="INSERT INTO nas(nasname, shortname, secret) VALUES";

# Cadastrar concentrador GLOBALv4 para permitir todos os enderecos IPv4
_sql "DELETE FROM nas WHERE shortname = 'GLOBALv4';";
_sql "$IN ('0.0.0.0/0', 'GLOBALv4', 'tulipa');";

# Cadastrar concentrador GLOBALv6 para permitir todos os enderecos IPv6
_sql "DELETE FROM nas WHERE shortname = 'GLOBALv6';";
_sql "$IN ('::/0', 'GLOBALv6', 'tulipa');";

# Conferindo:
_sql "SELECT * FROM nas;";

x

x

x

x

(parei aqui, estou escrevendo em tempo real)

.

.

.

O foco não deve ser o problema, mas, sim,
sua atitude em relação ao problema.”
Capitão Jack Sparrow

Terminamos por hoje!

Patrick Brandão, patrickbrandao@gmail.com