HOWTO: High Available HTTP Load Balancer with Nginx Reverse Cached Proxy+ Keepalived + Repcached PHP Session Sharing + Rsync mirroring + SSL
1. Introdução
Este artigo demonstra a configuração de um ambiante de alta disponibilidade para serviços web. Ele poderia ser dividido em vários artigos independentes abordando cada etapa e instalação de cada software, mas reuni todas as informações em um único artigo que aborda um ambiente completo de alta disponibilidade, balanceamento de carga e cache (proxy reverso) de um ambiente web multiplataforma, como Apache + PHP ou Apache + Tomcat por exemplo.
2. Softwares Utilizados
Utilizaremos o keepalived para fornecer failover de endereçamento IP e checagem de estado dos servidores web. Assim se um dos nós ficar fora de operação, o keepalived, através da sua checagem de estado, cuidará de configurar os devidos endereços e rotas IP nos nós que assumirão o serviço anteriormente de outro servidor.
Já o Nginx (leia-se engine X) é um rápido e leve servidor web e proxy reverso. Sua arquitetura interna otimizada, permite servir centenas de conexões com um pequeno overhead de CPU e memória. Nesta configuração usaremos o Nginx como um proxy reverso, onde as requisições das páginas dos nossos servidores web chegarão primeiramente ao Nginx que por sua vez realizará o balanceamento de carga entre os servidores web Apache servirão as páginas solicitadas. No nosso cenário utilizaremos também o Nginx para servir o conteúdo estático dos sites (como imagens, arquivos pdf, css, js etc), já que ele é muito mais rápido que o apache fazendo este serviço. Utilizaremos também a opção de fazer cache das páginas solicitadas, assim o Nginx pode responder uma página que já esteja em cache sem precisar abrir nenhuma conexão com os servidores Apache ou Tomcat, deixando-os livres pra processar o que realmente é necessário, no caso o conteúdo dinâmico como PHP, JSP etc.
As sessões são salvas por padrão nas mesmas máquinas que servem o PHP. O que implica que temos que garantir que nossos usuários sejam direcionados para o mesmo servidor web. Mas nosso balanceamento de carga dividirá equalitáriamente as requisições entre os servidores web, então uma sessão iniciada em um servidor não será reconhecida nos outros servidores membros do cluster. Para resolver esse problema utilizaremos o repcached, que é um patch para o memcached, que por sua vez é um sistema que permite realizar cache de quase todo tipo de objetos (como resultados de funções, resultados de consultas de bancos de dados etc) em memória RAM. Realizar cache em memória ao invés carregar dados de um banco de dados, pode aumentar significativamente a performance de sistemas PHP.
O repcached adiciona suporte à replicação dos dados do memcached entre os nós do cluster, assim uma sessão que seja armazenada no repcached de um nó estará disponível em qualquer outro nó do cluster, e se este nó inicial vier a ficar indisponível poderá resgatar os seus dados armazenados nos outros membros do cluster quando voltar a ficar on-line.
Assim sessões estarão ser compartilhadas entre todos os servidores que farão parte do nosso cluster, já que não temos como saber para qual servidor web o usuário será balanceado a cada solicitação.
Como nosso todos os nós do nosso cluster de alta disponibilidade web vai servir o mesmo conteúdo, isto é, as mesmas páginas, temos que estar certificados que eles estejam sincronizados entre si. A solução mais fácil seria utilizar um storage e um sistema de arquivos distribuído como ocfs2 ou gfs conectado aos servidores, mas como nem sempre temos um equipamento como esse disponível, recorremos a outras soluções.
Poderíamos usar um diretório compartilhado por NFS e montado em todos os servidores, mas continuaríamos assim com um gargalo que seria a alta taxa de I/O na rede.
Optamos por usar uma simples solução de espelhamento utilizando rsync nos diretórios publicados nos servidores web.Existem outras opções mais avançadas de espelhamento pela rede como o DRBB e sistemas de arquivos distribuídos como o GlusterFS que exigiriam um artigo específico falando sobre eles, mas para o nosso ambiente o rsync é suficiente.
3. Cenário
Utilizaremos apenas dois servidores físicos utilizando Debian GNU/Linux 6 (squeeze) amd64 com uma instalação básica através da imagem netinst. Apesar de utilizar apenas dois servidores esta solução é bastante escalável podendo-se facilmente aumentar o número de nós do cluster de acordo com as necessidades.
As requisições aos websites servidos serão primeiramente recebidas no Nginx do Servidor A, denominado master, que realizará o balanceamento das requisições entre os Apache dos Servidores A e B (back end servers) conforme a imagem abaixo:
- Servidor A: 10.10.10.1
- Servidor B: 10.10.10.2
- IP Virtual (VIP): 10.10.10.10
A fim de se evitar um Ponto Único de Falhas, (SPOF, Singe Point of Failure) realizaremos o chamado failover entre os processos Nginx, assim caso o Nginx do Servidr A venha a falhar o Servidor B assumirá seu papel evitando que todo o sistema venha a ficar indisponível, mesmo estando os servidores web de pé e funcionando. Temos, portanto, dois níveis de Alta Disponibilidade, entre os balanceadores de carga (NginX) e entre os Servidores Web A e B (Apache), pois caso um deles fique indisponível as requisições serão direcionadas apenas ao outro servidor até que o servidor defeituoso volta a ficar on-line. A ilustração abaixo demonstra o cenário em possíveis falhas:
- Falha 1 (Servidor B totalmente inoperante):
Enquanto o Servidor B estiver indisponível, as requisições serão encaminhadas somente ao Servidor A.
- Falha 2 (Processo Nginx do Servidor A com problemas):
Aqui temos um problema com o processo balanceador de carga do Servidor A, porém o servidor web Apache está funcionando e pronto para receber requisições. O Keepalived reconhecerá que o Nginx do Servidor A caiu e o Servidor B ira atribuir para si o IP Virtual e tornara-se o balanceador de carga do sistema, encaminhando as requisições aos Apache dos Servidores A e B.
- Falha 3 (Servidor A recupera-se da falha e volta ao estado de Master)
O Servidor Web A tornase totalmente disponível novamente, tanto o processo balanceador de carga Nginx quando o servidor web Apache. Então o keepalived atribui novamente o IP Virtual para o Servidor A e este volta ao estado original do sistema, balanceando as requisições entre os Apache dos Servidores A e B.
4. Instalação
4.1 Keepalived
Os seguintes comandos devem ser executados nos dois servidores membros do balanceamento de cargo, Servidores A e B.
Instalamos o keepalived pelo apt-get:
apt-get install keepalived
Após, temos que editar o sysctl.conf e ativar a opção net.ipv4.ip_nonlocal_bind para permitir que processos escutem em endereços IP ainda não atribuídos:
echo net.ipv4.ip_nonlocal_bind=1 >> /etc/sysctl.conf sysctl -p
Daqui pra frente a configuração será dividida entre os Servidores A e B, já que possuem detalhes pertinentes a cada um.
Executaremos os seguintes comandos no Servidor A, que será denominado master no keepalived:
Criaremos o arquivo de configuração do keepalived em /etc/keepalived/keepalived.conf com o seguinte conteúdo:
vrrp_script chk_http_port {
script "/usr/bin/killall -0 nginx"
interval 2
weight 2
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 53
priority 101 # 101 on master, 100 on backup
authentication {
auth_type PASS
auth_pass som3_an0th3r_p4ss
}
track_script {
chk_http_port
}
virtual_ipaddress {
10.10.10.10/24 dev eth0
}
}
O que instrui o keepalived a ficar monitorando o status os processos nginx. Enquanto o processo estiver rodando, os endereços ip definidos na seção virtual_ipaddress (10.10.10.10)serão atribuídos ao servidor. Caso o processo venha a cair, ou o servidor inteiro ficar inoperante, o outro nó detectará e caso o seu processo nginx esteja de pé ele auto configurará o endereço ip virtual neste servidor, mantendo assim o serviço sempre de pé.
Os parâmetros virtual_router_ip e priority configura valores do protocolo de redundância vrrp. Deve-se setar o mesmo valor de virtual_router_id para todos
os nós participantes do balanceamento. Já o valor de priority deve ser o maior no servidor master, aquele que iniciará com o endereço ip virtual atribuído,
e valores inferiores a este nos servidores backups.
Agora configuraremos o keepalived do Servidor B.
Criaremos o arquivo de configuração do keepalived em /etc/keepalived/keepalived.conf com o seguinte conteúdo:
vrrp_script chk_http_port {
script "/usr/bin/killall -0 nginx";
interval 2
weight 2
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 53
priority 100 # 101 on master, 100 on backup
authentication {
auth_type PASS
auth_pass som3_an0th3r_p4ss
}
track_script {
chk_http_port
}
virtual_ipaddress {
10.10.10.10/24 dev eth0
}
}
Depois de salvos os arquivos, devemos iniciar o processo keepalived nos Servidores A e B:
service keepalived start
Após isso, mensagens da inicialização do keepalived poderão ser vistas nos logs, em especial em /var/log/messages.
Jan 18 10:50:34 servidorA Keepalived_vrrp: Registering Kernel netlink reflector Jan 18 10:50:34 servidorA Keepalived_vrrp: Registering Kernel netlink command channel Jan 18 10:50:34 servidorA Keepalived_vrrp: Registering gratutious ARP shared channel Jan 18 10:50:34 servidorA Keepalived_vrrp: IPVS: Can't initialize ipvs: Protocol not available Jan 18 10:50:34 servidorA Keepalived_vrrp: Opening file '/etc/keepalived/keepalived.conf'. Jan 18 10:50:34 servidorA Keepalived_vrrp: Configuration is using : 62094 Bytes Jan 18 10:50:34 servidorA Keepalived_vrrp: Using LinkWatch kernel netlink reflector... Jan 18 10:50:34 servidorA Keepalived_healthcheckers: IPVS: Can't initialize ipvs: Protocol not available Jan 18 10:50:34 servidorA Keepalived_healthcheckers: Registering Kernel netlink reflector Jan 18 10:50:34 servidorA Keepalived_healthcheckers: Registering Kernel netlink command channel Jan 18 10:50:34 servidorA Keepalived_healthcheckers: Opening file '/etc/keepalived/keepalived.conf'. Jan 18 10:50:34 servidorA Keepalived_healthcheckers: Configuration is using : 4249 Bytes Jan 18 10:50:34 servidorA Keepalived_healthcheckers: Using LinkWatch kernel netlink reflector... Jan 18 10:50:35 servidorA Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE Jan 18 10:50:36 servidorA Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE
Verificaremos se o endereço ip virtual foi atribuído ao servidor master do balanceamento com sucesso:
ip addr show dev eth0
O que no Servidor Web A retorna:
root@servidorA:~# ip addr show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether 54:52:00:07:9c:2e brd ff:ff:ff:ff:ff:ff inet 10.10.10.1/24 brd 10.10.10.255 scope global eth0 inet 10.10.10.10/24 scope global secondary eth0 inet6 fe80::5652:ff:fe07:9c2e/64 scope link valid_lft forever preferred_lft forever
Já oServidor Web B retorna:
root@servidorB:~# ip addr show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether 54:52:00:00:00:ac brd ff:ff:ff:ff:ff:ff inet 10.10.10.2/24 brd 10.10.10.255 scope global eth0 inet6 fe80::5652:ff:fe00:ac/64 scope link valid_lft forever preferred_lft forever
Como podemos ver o endereço IP Virtual (VIP) está atribuído ao Servidor Web A, que é o servidor master do keepalived pois possui um valor da diretiva priority maior.
Podemos testar se o failover está realmente funcionando parando o serviço keepalived no Servidor Web A. Neste caso o Servidor Web B identificará o problema e atribuirá para si o endereço IP Virtual.
Paramos o keepalived no Servidor Web A:
service keepalived stop
Após poucos segundos, verificaremos os endereços IP atribuídos ao Servidor Web B:
root@servidorB:~# ip addr show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether 54:52:00:00:00:ac brd ff:ff:ff:ff:ff:ff inet 10.10.10.2/24 brd 10.10.10.255 scope global eth0 inet 10.10.10.10/24 scope global secondary eth0 inet6 fe80::5652:ff:fe00:ac/64 scope link valid_lft forever preferred_lft forever
Como vimos o endereço IP foi atribuído com sucesso ao Servidor B, garantindo failover IP.
4.2 Apache
Para exemplificar, iremos hospedar um domínio no nosso sistema com as seguintes características:
Endereço DNS: www.exemplo.com
Endereço IP: 10.10.10.10
Como vemos, os nossos sites precisam resolver para o endereço IP Virtual, que por sua vez balanceará as solicitações entre os Servidores Web.
Instalaremos o Apache com apenas as configurações necessárias para o nosso sistema funcionar, opções de hardenização e segurança não serão abordadas aqui.
Os comandos desta seção devem ser executados em ambos os Servidores Web A e B:
apt-get install apache2 php5
Para que o Apache possa logar corretamente o IP do cliente que será encaminhado pelo Nginx, devemos localizar e substituir as seguintes linhas de definições de log no arquivo /etc/apache2/apache2.conf:
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
por
#LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%v %{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
Agora criaremos o arquivo de definições do VirtualHost do nosso domínio em /etc/apache2/sites-available/www.exemplo.com
<VirtualHost *:81> DocumentRoot "/var/www" ServerName www.exemplo.com ErrorLog "/var/log/apache2/www.exemplo.com.error_log" CustomLog "/var/log/apache2/www.exemplo.com.access_log" common </VirtualHost>
Agora ativamos o VirtualHost criado:
a2ensite www.exemplo.com
No arquivo /etc/apache2/ports.conf localizaremos as seguintes diretivas que configuram as portas nas quais o apache escuta:
NameVirtualHost *:80 Listen 80
e substiruiremos por:
NameVirtualHost *:81 Listen 81
O mesmo deve ser feito para o arquivo do VirtualHost padrão, caso este esteja ativado, localizado em /etc/apache2/sites-available/default:
Substituir:
<VirtualHost *:80>
por:
<VirtualHost *:81>
Conferimos se há algum erro de configuração:
root@servidorA:~# apache2ctl configtest Syntax OK
Agora reiniciamos o Apache:
apache2ctl restart
4.3 Nginx
Os comandos desta seção devem ser executados em ambos os Servidores Web A e B:
Instalamos o pacote via apt-get:
apt-get install nginx
Utilizaremos o seguinte arquivo de configuração /etc/nginx/nginx.conf:
user www-data;
worker_processes 2;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
# multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server_names_hash_bucket_size 33;
}
Em seguida criaremos o arquivo /etc/nginx/conf.d/options.conf:
# Size Limits client_body_buffer_size 128K; client_header_buffer_size 128K; client_max_body_size 50M; # php's upload_max_filesize large_client_header_buffers 8 8k; proxy_buffers 8 16k; proxy_buffer_size 32k; # Timeouts client_body_timeout 60; client_header_timeout 60; expires off; keepalive_timeout 60 60; send_timeout 60; # General Options ignore_invalid_headers on; keepalive_requests 100; limit_zone gulag $binary_remote_addr 5m; recursive_error_pages on; sendfile on; server_name_in_redirect off; server_tokens off; # TCP options tcp_nodelay on; tcp_nopush on; # Compression gzip on; gzip_buffers 16 8k; gzip_comp_level 6; gzip_http_version 1.0; gzip_min_length 0; gzip_types text/plain text/css image/x-icon application/x-perl application/x-httpd-cgi; gzip_vary on; # Log Format log_format main '$remote_addr $host $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent" ' '"$gzip_ratio"'; proxy_cache_path /var/cache/nginx/ levels=1:2 keys_zone=cache:100m inactive=1h max_size=1024M;
Na sequência criaremos o arquivo /etc/nginx/conf.d/proxy.conf:
proxy_cache_valid 1h; # 200, 301 and 302 will be cached.
proxy_cache_use_stale error
timeout
invalid_header
http_500
http_502
http_504
http_404;
proxy_buffering on;
proxy_cache_min_uses 3;
proxy_ignore_client_abort off;
proxy_intercept_errors on;
proxy_next_upstream error timeout invalid_header;
proxy_redirect off;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_ignore_headers Expires Cache-Control;
proxy_cache_key "$scheme$host$uri$is_args$args";
E o arquivo /etc/nginx/conf.d/upstream.conf:
upstream lb {
server 10.10.10.1:81 max_fails=10 fail_timeout=300s; # Web Server A
server 10.10.10.2:81 max_fails=10 fail_timeout=300s; # Web Server B
}
Crie o arquivo de definições do domínio no Nginx /etc/nginx/sites-available/www.exemplo.com com o seguinte conteúdo:
server {
listen 10.10.10.10:80;
server_name www.exemplo.com;
access_log /var/log/nginx/www.exemplo.com.access.log;
location / {
proxy_pass http://lb;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Agora, uma explicação mais detalhada dos principais parâmetros setados nestes arquivos de configuração:
- user www-data; Define com qual usuário o processo nginx será iniciado.
- worker_processes 2; Define o número de threads do nginx. Geralmente seta-se este valor com o número de núcleos da CPU do servidor. É sempre importante manipular esse valor fazendo um benchmark de conexões.
- worker_connections 1024; Número máximo de conexões por worker. Para saber o número de conexões do servidor multiplique: max_clients = worker_processes * worker_connections
- proxy_cache_valid 1h; Período em que um hit pode ficar no cache. Caso um objeto entre no cache, ele passará 1h marcado como válido, e o servidor o usará quando tal objeto for requisitado. Após expirado esse tempo o objeto sai do cache e novas requisições por ele serão realizadas diretamente aos servidores backend.
- upstream lb; Define um conjunto de servidores e portas para onde serão encaminhadas as requisições que não estiverem em cache. O nginx balanceará as requisições de forma equalitária entre os servidores usando o método round-robin.
- listen 10.10.10.10:80; Endereço e porta onde o Nginx escutará por conexões.
- server_name www.exemplo.com; Endereço DNS do VirtualHost.
- proxy_pass http://lb; Encaminha as requisições ao upstream lb definido no arquivo upstream.conf.
Agora criamos o link que ativa o VirtualHost para o diretório /etc/nginx/sites-enabled:
cd /etc/nginx/sites-enabled/ ln -s ../sites-available/www.exemplo.com.br
Criamos também o diretório onde será armazenado o cache do Nginx e setamos suas permissões:
mkdir /var/cache/nginx/ chown -R www-data:www-data /var/cache/nginx/
Vamos testar a configuração do Nginx antes de inicia-lo, caso exista algum erro nos arquivos de configuração este teste acusará:
root@servidorA:~# nginx -t the configuration file /etc/nginx/nginx.conf syntax is ok configuration file /etc/nginx/nginx.conf test is successful
Agora, podemos iniciar o serviço Nginx nos Servidores A e B:
service nginx start
Agora temos o nosso cluster de alta disponibilidade parcialmente completo, mas já podemos testar o FailOver IP e a distribuição das conexões entre os backends.
Criaremos um arquivo dentro do diretório /var/www de cada servidor com o hostname do servidor:
root@servidorA:~# hostname -f >> /var/www/index.html
Agora iremos abrir no Navegador o endereço do site que acabamos de configurar e pressionando o botão Atualizar por várias vezes, poderemos ver que ele o sistema está balanceando as conexões entre os dois servidores web.
4.4 Repcached
Utilizaremos o repcached para replicar as sessões dos sistemas que rodarão nos dois servidores, assim usuários logados em um servidor não perderão suas sessões quando balanceados para o outro servidor.
Os comandos a seguir devem ser executados em ambos Servidores A e B.
Temos que editar os seguintes valores na seção Session do arquivo /etc/php5/apache2/php.ini:
[Session] session.save_handler = memcache session.save_path = "tcp://10.10.10.1:11211, tcp://10.10.10.2:11211"
Assim dizemos ao php para gravar as seções no memcache, e informamos os endereços IP dos servidores que farão parte da replicação.
Editamos também o arquivo /etc/php5/conf.d/memcache.ini:
memcache.maxratio=0 memcache.allow_failover=1
Agora procedemos com a instalação do memcached:
apt-get install memcached
Após isso devemos baixar o código-fonte do repcached, compilar e instala-lo no servidor. Infelizmente o repcached ainda não é empacotado no repositório oficial do Debian.
cd /usr/src/ wget "http://ufpr.dl.sourceforge.net/project/repcached/repcached/2.2-1.2.8/memcached-1.2.8-repcached-2.2.tar.gz" tar zxvf memcached-1.2.8-repcached-2.2.tar.gz cd memcached-1.2.8-repcached-2.2 ./configure --enable-replication make make install
No Servidor A usaremos o seguinte arquivo de configuração /etc/repcached.conf:
# repcached config file # 2011 - jean caffou # Run repcached as a daemon. This command is implied, and is not needed for the # daemon to run. See the README.Debian that comes with this package for more # information. -d # Log repcached's output to /var/log/repcached logfile /var/log/repcached.log # Be verbose # -v # Be even more verbose (print client commands as well) # -vv # Start with a cap of 64 megs of memory. It's reasonable, and the daemon default # Note that the daemon will grow to this size, but does not start out holding this much # memory -m 64 # Default connection port is 11211 -p 11211 # Run the daemon as root. The start-repcached will default to running as root if no # -u command is present in this config file -u nobody # Specify which IP address to listen on. The default is to listen on all IP addresses # This parameter is one of the only security measures that repcached has, so make sure # it's listening on a firewalled interface. # -l 127.0.0.1 # Limit the number of simultaneous incoming connections. The daemon default is 1024 # -c 1024 # Lock down all paged memory. Consult with the README and homepage before you do this # -k # Return error when memory is exhausted (rather than removing items) # -M # Maximize core file limit # -r # Port for server replication. Default is 11212 -X 11212 # IP for repcached peer server -x 10.10.10.2
E o seguinte no Servidor B:
# repcached config file # 2011 - jean caffou # Run repcached as a daemon. This command is implied, and is not needed for the # daemon to run. See the README.Debian that comes with this package for more # information. -d # Log repcached's output to /var/log/repcached logfile /var/log/repcached.log # Be verbose # -v # Be even more verbose (print client commands as well) # -vv # Start with a cap of 64 megs of memory. It's reasonable, and the daemon default # Note that the daemon will grow to this size, but does not start out holding this much # memory -m 64 # Default connection port is 11211 -p 11211 # Run the daemon as root. The start-repcached will default to running as root if no # -u command is present in this config file -u nobody # Specify which IP address to listen on. The default is to listen on all IP addresses # This parameter is one of the only security measures that repcached has, so make sure # it's listening on a firewalled interface. # -l 127.0.0.1 # Limit the number of simultaneous incoming connections. The daemon default is 1024 # -c 1024 # Lock down all paged memory. Consult with the README and homepage before you do this # -k # Return error when memory is exhausted (rather than removing items) # -M # Maximize core file limit # -r # Port for server replication. Default is 11212 -X 11212 # IP for repcached peer server -x 10.10.10.1
Como podemos observar no final destes arquivos é informado o endereço IP do outro nó que vai rodar o repcached. Assim o Servidor A informa no seu arquivo de configuração o endereço IP do Servidor e vice-versa. Aproveitaremos alguns arquivos da instalação do memcached para usarmos no repcached:
cp /etc/default/memcached /etc/default/repcached
Em seguida editamos o arquivo /etc/default/repcached e alteramos a seguinte linha de:
ENABLE_MEMCACHED=no
para
ENABLE_REPCACHED=YES
E desativamos a inicialização do memcached editando o arquivo /etc/default/memcached de:
ENABLE_MEMCACHED=YES
para
ENABLE_MEMCACHED=no
Utilizaremos o seguinte script rc para o repcached, localizado em /etc/init.d/repcached:
#! /bin/sh
### BEGIN INIT INFO
# Provides: repcached
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: $local_fs
# Should-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start repcached daemon
# Description: Start up repcached, a high-performance memory caching daemon with replication
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/bin/memcached
DAEMONBOOTSTRAP=/usr/share/memcached/scripts/start-repcached
NAME=repcached
DESC=repcached
PIDFILE=/var/run/$NAME.pid
test -x $DAEMON || exit 0
test -x $DAEMONBOOTSTRAP || exit 0
set -e
. /lib/lsb/init-functions
# Edit /etc/default/repcached to change this.
ENABLE_REPCACHED=no
test -r /etc/default/repcached && . /etc/default/repcached
case "$1" in
start)
echo -n "Starting $DESC: "
if [ $ENABLE_REPCACHED = yes ]; then
start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP
echo "$NAME."
else
echo "$NAME disabled in /etc/default/repcached."
fi
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON
echo "$NAME."
rm -f $PIDFILE
;;
restart|force-reload)
#
# If the "reload" option is implemented, move the "force-reload"
# option to the "reload" entry above. If not, "force-reload" is
# just the same as "restart".
#
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
rm -f $PIDFILE
sleep 1
start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP
echo "$NAME."
;;
status)
status_of_proc $DAEMON $NAME
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac
exit 0
Substituiremos também o arquivo /usr/share/memcached/scripts/start-repcached pelo o seguinte:
#!/usr/bin/perl -w
# start-repcached
# 2011 - Jean Caffou <jean@briskula.si>
# This script handles the parsing of the /etc/repcached.conf file
# and was originally created for the Debian distribution.
# Anyone may use this little script under the same terms as
# memcached itself.
use strict;
if($> != 0 and $< != 0)
{
print STDERR "Only root wants to run start-repcached.\n";
exit;
}
my $params; my $etchandle; my $etcfile = "/etc/repcached.conf";
# This script assumes that repcached is located at /usr/local/bin/memcached, and
# that the pidfile is writable at /var/run/repcached.pid
my $memcached = "/usr/local/bin/memcached";
my $pidfile = "/var/run/repcached.pid";
# If we don't get a valid logfile parameter in the /etc/repcached.conf file,
# we'll just throw away all of our in-daemon output.
my $fd_reopened = "/dev/null";
sub handle_logfile
{
my ($logfile) = @_;
$fd_reopened = $logfile;
}
sub reopen_logfile
{
my ($logfile) = @_;
open *STDERR, ">>$logfile";
open *STDOUT, ">>$logfile";
open *STDIN, ">>/dev/null";
$fd_reopened = $logfile;
}
# This is set up in place here to support other non -[a-z] directives
my $conf_directives = {
"logfile" => \&handle_logfile,
};
if(open $etchandle, $etcfile)
{
foreach my $line (<$etchandle>)
{
$line ||= "";
$line =~ s/\#.*//g;
$line =~ s/\s+$//g;
$line =~ s/^\s+//g;
next unless $line;
next if $line =~ /^\-[dh]/;
if($line =~ /^[^\-]/)
{
my ($directive, $arg) = $line =~ /^(.*?)\s+(.*)/;
$conf_directives->{$directive}->($arg);
next;
}
push @$params, $line;
}
}else{
$params = [];
}
push @$params, "-u root" unless(grep "-u", @$params);
$params = join " ", @$params;
if(-e $pidfile)
{
open PIDHANDLE, "$pidfile";
my $localpid = <PIDHANDLE>;
close PIDHANDLE;
chomp $localpid;
if(-d "/proc/$localpid")
{
print STDERR "repcached is already running.\n";
exit;
}else{
`rm -f $localpid`;
}
}
my $pid = fork();
if($pid == 0)
{
reopen_logfile($fd_reopened);
exec "$memcached $params";
exit(0);
}else{
if(open PIDHANDLE,">$pidfile")
{
print PIDHANDLE $pid;
close PIDHANDLE;
}else{
print STDERR "Can't write pidfile to $pidfile.\n";
}
}
Em seguida configuramos a inicialização do repcached durante o boot do sistema:
chmod +x /etc/init.d/repcached update-rc.d repcached defaults
Iniciamos o repcached:
service repcached start
Agora vamos fazer um teste para estarmos seguros de que a replicação de sessão esteja funcionando corretamente:
Primeiro, no Servidor A iremos escrever uma chave chamada "mykey" com o valor "12345" e recuperaremos seu valor no Servidor B:
[user@host ~]$telnet 10.10.10.1 11211 Trying 10.10.10.1... Connected to 10.10.10.1 Escape character is '^]'. set mykey 1 600 5 12345 STORED get mykey VALUE mykey 1 5 12345 END
Após isso, a chave deve ter sido replicada para o Servidor B, onde recuperaremos seu valor:
[user@host ~]$telnet 10.10.10.2 11112 Trying 10.10.10.2... Connected to 10.10.10.2 Escape character is '^]'. get mykey VALUE mykey 1 5 12345 END
Como vimos o valor do objeto mykey foi setado no Servidor A, replicado e recuperado no Servidor B. Agora temos nossa configuração do repcached funcionando perfeitamente.
4.5 Rsync Mirror
Iremos configurar o rsync para sincronizar o conteúdo do diretório /var/www do Servidor A para o Servidor B, assim deveremos copiar os arquivos para os sites no Servidor A que automaticamente os copiará para o Servidor B. Portanto serviços como FTP, usados para atualizar os dados dos websites servidos, devem ser instalados no Servidor A.
apt-get install rsync
Em seguida criaremos um usuário rsync nos dois hosts e configuraremos autenticação por chaves RSA no ssh, para não haver a pergunta de senha a cada vez que o comando for executado:
No Servidor B:
root@servidorB:~# useradd rsync -c "Rsync User" -d /var/www/ -s /bin/false root@servidorB:~# mkdir ~rsync/.ssh root@servidorB:~# chown rsync:root /var/www /var/www/.ssh root@servidorB:~# chmod 0755 /var/www root@servidorB:~# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 6f:5b:a1:6b:e9:f6:78:4e:a1:9f:f4:86:79:73:cd:46 root@marina The key's randomart image is: +--[ RSA 2048]----+ | | | | | | | | | S o | | . o o E| | =.+o o.| | .+O+o+ =| | +=+=o.+ | +-----------------+
No Servidor A:
root@servidorA:~# useradd rsync -c "Rsync User" -d /var/www/ -s /bin/bash root@servidorA:~# chown rsync:root /var/www root@servidorA:~# chmod 0755 /var/www
Agora copiamos o conteúdo da chave recém-criada do Servidor B para o Servidor A conforme os passos abaixo:
Servidor B:
root@servidorB:~# scp /root/.ssh/id_rsa.pub root@10.10.10.1:~rsync/.ssh/authorized_keys
E setamos as devidas permissões dos arquivos criados no Servidor A:
root@servidorA:~# chown -R rsync:rsync ~/rsync/.ssh/ root@servidorA:~# chmod 0600 ~/rsync/.ssh/authorized_keys
Agora criaremos um diretório no Servidor A, e em seguida executaremos o rsync no Servidor B, que deverá sincronizar os dois diretórios:
Servidor A:
root@servidorA:~# mkdir /var/www/rsync-test
Servidor B:
root@servidorB:~# rsync -av --delete rsync@10.10.10.1/var/www/ /var/www/
Se o rsync copiou o diretório criado no Servidor A para o Servidor B, nossa configuração está correta. Basta apenas adicionar o comando ao cron para ser executado de minuto a minuto para manter os diretórios o mais sincronizados possíveis.
No Servidor A abrimos o arquivo crontab do usuário root com o seguinte comando:
crontab -e
E adicionamos a seguinte linha:
# rsync */1 * * * * rsync -a --delete rsync@10.10.10.1:/var/www/ /var/www/
A configuração da sincronização do Servidor A para o Servidor B foi concluída e será executada uma vez a cada minuto.
4.6 Suporte SSL
Se desejarmos utilizar https nos sites hospedados em nosso cluster de alta disponibilidade, deveremos configurar os certificados digitais no Nginx. Já o Apache deve servir os sites em texto plano como mostra a figura abaixo:
Vamos adicionar suporte SSL ao VirtualHost www.exemplo.com que já foi configurado no Nginx. Vamos assumir que já temos os certificados SSL em mãos, porém se você precisar de um certificado SSL válido e gratuito recomendo o htttp://www.startssl.com que possui suporte na maioria dos navegadores e possui uma versão gratuita de certificados válidos.
Usaremos o seguinte arquivo /etc/nginx/sites-available/www.exemplo.com:
server {
listen 10.10.10.10:443;
server_name www.exemplo.com;
access_log /var/log/nginx/www.exemplo.com.access.log;
error_log /var/log/nginx/www.exemplo.com.error.log;
ssl on;
ssl_certificate /etc/apache2/ssl.crt/www.exemplo.com.crt;
ssl_certificate_key /etc/apache2/ssl.key/www.exemplo.com.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_protocols TLSv1;
ssl_ciphers HIGH:!ADH:!MD5;
ssl_prefer_server_ciphers on;
keepalive_timeout 60;
location / {
proxy_pass http://lb;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
4.7 Ativando o Cache do Nginx
A opção de cache do Nginx deve ser usada com cuidado, principalmente quando estamos servindo conteúdo dinâmico ou páginas de sistemas.
Uma boa aplicação do cache seria em páginas estáticas muito acessadas, por exemplo resultados de concursos, páginas iniciais de instituições entre outras aplicações.
Por exemplo, queremos ativar o cache da página www.exemplo.com/fotos/
Iremos alterar o arquivo de configuração /etc/nginx/sites-enabled/www.exemplo.com:
location /fotos/ {
proxy_pass http://lb;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# cache settings
include /etc/nginx/conf.d/proxy.conf;
proxy_cache cache;
}
As principais diretivas que controlam como o cache funciona são:
- proxy_cache_min_uses 3; Define o número de hits necessários para uma página entrar em cache. Neste exemplo caso a página configurada seja acessada por 3 vezes ela será inclusa no cache do Nginx por um período de tempo definido na diretiva proxy_cache_valid, e durante este intervalo o servidor Apache não será consultado para esta página.
- proxy_cache_key "$scheme$host$uri$is_args$args"; Define a chave que será utilizada para os objetos em cache. No exemplo utilizamos a URL completa com argumentos, mas poderíamos setar cookies nas aplicações para que determinadas páginas não entrassem no cache;
- proxy_cache_valid 1h; Período de tempo em que uma página pode permanecer no cache. Após expirado este tempo, a página volta a ser consultada nos servidores back end e após proxy_cache_min_uses vezes ela voltará ao cache.
Para mais informações à respeito das diretivas do Nginx recomendo a leitura da documentação on-line no Wiki do projeto em: http://wiki.nginx.org/Modules.
LPIC-02 pass
Dear Candidate,
LPI ID: LPI000116018
Congratulations on obtaining your LPIC-2 certification.
Exams
| Exam | Date | Grade | Details | |
|---|---|---|---|---|
| 101 | 2006-08-05 00:00:00 | pass | details | |
| 102 | 2006-08-05 00:00:00 | pass | details | |
| 201 | 2010-10-21 15:17:57 | pass | details | |
| 202 | 2010-10-22 15:31:35 | pass | details |
No dia 19 de Dezembro vou fazer a prova 301, necessária para a Senior Level Linux Professional (LPIC-3).
Overview of Tasks: to pass LPIC-3 “Core” someone should:
- Have several years experience with installing and maintaining Linux on a number of computers for various purposes
- Have integration experience with diverse technologies and operating systems
- Have professional experience as, or training for, an enterprise level Linux professional. (Including having experience as a part of another role)
- Know advanced and enterprise levels of Linux administration including installation, management, security, troubleshooting and maintenance
- Be able to use open source tools to measure capacity planning and troubleshoot resource problems
- Have professional experience using LDAP to integrate with Unix services and Windows services, including Samba, PAM, email, Active Directory
- Be able to plan, architecture, design, build and implement a full environment using Samba and LDAP as well as measure the capacity planning and security of the services
- Be able create scripts in Bash or Perl or has knowledge of at least one system programming language (such as C)
Como a prova praticamente aborda integração com OpenLDAP estou tomando como material de estudos o livro "OpenLDAP - Uma abordagem integrada" de Clodonil Honório Trigo, que a meu ver aborda todos os tópicos descritos na sessão objetivos detalhados do da prova 301. Como adição tenho lido também o material disponibilizado em http://www.rootkit.nl/files/book_lpic-3_301.html.
Coincidentemente, no momento estou trabalhando em um projeto de centralização, integração e single SignOn da base de usuários entre vários sistemas e serviços.
Para o exame LPIC-02 utilizei o livro Certificação Linux LPI: Nível 2 Exames 201 e 202 de Steven Pritchard, O'Reilly. Um bom livro que abordou bem todos os tópicos cobrados no meu exame.
Aumentando o limite de interfaces de rede do qemu.
Quem utiliza o Linux KVM como plataforma de virtualização e utiliza VM's com muitas interfaces de rede (notavelmente gateways acessando várias VLANS) já deve ter se deparado com um erro do qemu dizendo que se ultrapassou o número máximo de interfaces de rede permitido.
O número máximo de interfaces de rede é definido em tempo de compilação em um header (qemu/net.h) do qemu. Para aumentarmos esse limite será necessário o código-fonte do qemu:
Ocorre o seguinte erro ao iniciarmos uma VM com mais de 8 interfaces de rede:
qemu: Too Many NICs Tomando como base um sistema Debian GNU/Linux:mkdir /usr/src/qemu cd /usr/src/qemuBaixe o fonte do qemu:
apt-get source qemu cd qemu-0.9.1/
edite o arquivo net.h
vim net.hAltere a constante MAX_NICS de 8 para o valor que vc deseja. (Testei com 12 NIC's e não tive problemas.):
#define MAX_NICS 12Compile o pacote qemu: (execute o comando de dentro do diretório qemu-0.9.1)
dpkg-buildpackage -rfakeroot -uc -bNesse ponto tive que instalar algumas dependências tanto do ambiente quanto do qemu, isso varia de ambiente para ambiente, entretanto resolvi as minhas dependências intalando:
apt-get install libsdl1.2-dev apt-get install debhelper debhelper quilt nasm gcc-3.4 fakeroot apt-get install libx11-dev zlib1g-dev texi2html libgnutls-dev libasound2-dev libgpmg1-dev libbrlapi-devDesinstalar o qemu original:
apt-get purge qemuDepois de compilado o pacote .deb será construído em um diretório acima (/usr/src/qemu no meu caso):
cd .. apt-get install qemu_0.9.1-10lenny1_amd64.deb
Fornecendo rotas estáticas (classless static routing) pelo dhcpd.
Esta solução é bastante interessante, e um tanto pouco documentada, quando se utiliza roteamento inter-vlans em um switch nível 3 por exemplo. Ao invés do gateway da rede fazer o roteamento entre todas as vlans podemos utilizar o próprio switch e fornecer estas rotas às estações através do dhcpd.
O dhcpd por padrão fornece um mecanismo de fornecer rotas estáticas (option static-routes), porém não são permitidas rotas para redes inteiras, apenas para hosts.
Desta forma é mostrada uma solução que permite fazer roteamento para redes com máscaras não cheias (classless).
Nas definições globais do dhcpd.conf adicione as linhas:
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
option ms-classless-static-routes code 249 = array of unsigned integer 8;
As linhas definem a RFC3442 (The Classless Static Route Option for Dynamic Host Configuration Protocol (DHCP) version 4) sendo o code 121 a implementação RFC e o code 249 a implementação Microsoft desta RFC (no caso de clientes dhcp Windows.
Depois de definidas estas opções, podemos definir as rotas dentro de cada bloco subnet:
option rfc3442-classless-static-routes 24, 10, 1, 2, 10, 1, 1, 254;
option ms-classless-static-routes 24, 10, 1, 2, 10, 1, 1, 254;
As linhas adicionam uma rota para a rede 10.1.2.0/24 utilizando o gateway 10.1.1.254. Para tal, usa-se a seguinte regra de produção:
[netmask, network address byte 1, network address byte 2, network address byte 3, route byte 1, route byte 2, route byte 3, route byte 4]
Exemplo:
dhcpd.conf: (estou mostrando apenas as opções relevantes ao assunto, insira os parâmetros pertinentes ao seu cenário)
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
option ms-classless-static-routes code 249 = array of unsigned integer 8;
subnet 10.1.1.0 netmask 255.255.255.0 {
range 10.1.1.100 10.1.1.200;
option broadcast-address 10.1.1.255;
option routers 10.1.1.1;
option rfc3442-classless-static-routes 24, 10, 1, 2, 10, 1, 1, 254,
24, 10, 1, 3, 10, 1, 1, 254,
24, 10, 1, 4, 10, 1, 1, 254,
24, 10, 1, 5, 10, 1, 1, 254,
24, 10, 1, 6, 10, 1, 1, 254,
24, 10, 1, 7, 10, 1, 1, 254;
option ms-classless-static-routes 24, 10, 1, 2, 10, 1, 1, 254,
24, 10, 1, 3, 10, 1, 1, 254,
24, 10, 1, 4, 10, 1, 1, 254,
24, 10, 1, 5, 10, 1, 1, 254,
24, 10, 1, 6, 10, 1, 1, 254,
24, 10, 1, 7, 10, 1, 1, 254;
}
Criamos rotas para as subnets 10.1.2.0/24, 10.1.3.0/24, 10.1.4.0/24, 10.1.5.0/24, 10.1.6.0/24, 10.1.7.0/24 utilizando o gateway 10.1.1.254 (nossa switch nível 3 em questão) ao invés do gateway padrão 10.1.1.1.
Obs: Descobri que equipamentos rodando Android (2.3.5) não conseguem setar corretamente o gateway padrão em uma rede que use este recurso. Tive que definir a rota padrão manualmente no dispositivo para que ele pudesse conectar-se à Internet.
OpenLDAP + Samba Domain Controller On Ubuntu 7.10
From: RickyJones (http://www.howtoforge.com/openldap-samba-domain-controller-ubuntu7.10)
Preface
This document is a step by step guide for configuring Ubuntu 7.10 as a Samba Domain Controller with an LDAP backend (OpenLDAP). The point is to configure a server that can be comparable, from a central authentication point of view, to a Windows Server 2003 Domain Controller. The end result will be a server with an LDAP directory for storing user, group, and computer accounts. A Windows XP Professional SP2 workstation will be able to join the domain once properly configured. Please note that you do not have a fully comparable Windows domain controller at this time. Do not kid yourself, this guide only gets you a server with LDAP authentication. Of course this can be expanded to include slave servers to spread out authentication over multiple networks. Please also note that it took me approximately two and a half weeks to compile this information and get it working. The same functionality can be had in Windows in less than four hours (and this includes operating system installation). In my humble opinion the open source community will need to work on this side of Linux in order for it to be a true alternative to Windows.
Legal/Warranty/Etc...
This document is provided as-is with no implied warranty or agreement. I will not support other systems without compensation. This document is the property of Richard Maloley II. This document may be redistributed, copied, printed, and modified at will, however my name must remain as the original source. Legal action can and will be brought against any and all infractions of the terms.
Special Items of Interest
* My hostname during the installation was set to: dc01-ubuntu
* My fully qualified domain name will be: dc01-ubuntu.example.local
* After the installation my /etc/hostname was changed to: dc01-ubuntu.example.local
* After the installation my /etc/hosts was changed so that the line 127.0.1.1 contained "dc01-ubuntu dc01-ubuntu.example.local" to ensure no issues with name resolution.
* My LDAP domain is: example.local
* This translates to a Base DN of: dc=example,dc=local
* All passwords used are "12345" to keep things simple.
* I am not using TLS or SSL for my LDAP directory. Too much work for this tutorial.
* The user I created during the installation is: sysadmin
* The password I assigned during the installation is: 12345
* This local user will be used for all configuration purposes.
Assumptions
* Ubuntu Server 7.10 is installed.
* No other software was installed during the OS install!
* After installation you enabled all the repositories in /etc/apt/sources.list
* You fully updated your system
apt-get update
apt-get upgrade
reboot
* You configured a static IP address. For me I used the following information:
address 192.168.0.60
gateway 192.168.0.1
netmask 255.255.255.0
* You edited your /etc/hosts file so that your hostname and fully qualified domain name are on the line 127.0.1.1
127.0.1.1 dc01-ubuntu dc01-ubuntu.example.local
* You installed the OpenSSH Server.
apt-get install openssh-server
* You did not set a password on the root account. All commands will be run with sudo or by opening a root shell.
sudo bash
* Currently you do not have any other software running nor do you have any other users on the system.
Step 1: Install WebMin
We will be installing WebMin. Why? I like to use it to configure some things. This step is techinically optional but I feel as though it greatly simplifies administration of the server in the future.
# Download the WebMin package from their website.
wget http://superb-west.dl.sourceforge.net/sourceforge/webadmin/webmin_1.380_all.deb
# Install pre-requisite software.
apt-get install openssl libauthen-pam-perl libio-pty-perl libmd5-perl libnet-ssleay-perl
# Install WebMin
dpkg -i webmin_1.380_all.deb
# If the installation is successful you will see a message similar to this:
"Webmin install complete. You can now login to https://dc01-ubuntu.example.local:10000/
as root with your root password,
or as any user who can use sudo to run commands as root."
Step 2: Install OpenLDAP
For our LDAP server we will be using the very flexible OpenLDAP Server (slapd).
# Install the software.
apt-get install slapd ldap-utils migrationtools
# Answer the on-screen prompts with:
Admin password: 12345
Confirm password: 12345
# We need to configure OpenLDAP now.
dpkg-reconfigure slapd
# Answer the on-screen prompts with:
No
DNS domain name: example.local
Name of your organization: example.local
Admin password: 12345
Confirm password: 12345
OK
BDB
No
Yes
No
# Restart OpenLDAP.
/etc/init.d/slapd restart
Step 3: Install SAMBA
We will be using SAMBA for some main functions in this tutorial. In order to configure OpenLDAP correctly we must first install SAMBA.
# Install the software.
apt-get install samba smbldap-tools smbclient samba-doc
Step 4: Configure OpenLDAP for use with SAMBA
In order to use LDAP and SAMBA we need to configure the /etc/ldap/slapd.conf file.
# Copy the samba.schema file to the OpenLDAP schema directory.
cp /usr/share/doc/samba-doc/examples/LDAP/samba.schema.gz /etc/ldap/schema/
# Unzip the file.
gzip -d /etc/ldap/schema/samba.schema.gz
# Open the /etc/ldap/slapd.conf file for editing.
vim /etc/ldap/slapd.conf
# Add the following lines to the document where the other "include" lines are:
include /etc/ldap/schema/samba.schema include /etc/ldap/schema/misc.schema
# Change the line:
access to attribute=userPassword
# to:
access to attrs=userPassword,sambaNTPassword,sambaLMPassword
# Restart OpenLDAP:
/etc/init.d/slapd restart
Step 5: Configure SAMBA
Now we need to configure SAMBA. This includes configuring the /etc/samba/smb.conf file.
# Open up the SAMBA directory.
cd /etc/samba/
# Backup the samba configuration file.
cp smb.conf smb.conf.original
# Open the samba configuration file for editing.
vim smb.conf
# Make the following changes throughout the file:
workgroup = EXAMPLE security = user passdb backend = ldapsam:ldap://localhost/ obey pam restrictions = no ####################################################################### #COPY AND PASTE THE FOLLOWING UNDERNEATH "OBEY PAM RESTRICTIONS = NO" ####################################################################### # # Begin: Custom LDAP Entries # ldap admin dn = cn=admin,dc=example,dc=local ldap suffix = dc=example, dc=local ldap group suffix = ou=Groups ldap user suffix = ou=Users ldap machine suffix = ou=Computers ldap idmap suffix = ou=Users ; Do ldap passwd sync ldap passwd sync = Yes passwd program = /usr/sbin/smbldap-passwd %u passwd chat = *New*password* %n\n *Retype*new*password* %n\n *all*authentication*tokens*updated* add user script = /usr/sbin/smbldap-useradd -m "%u" ldap delete dn = Yes delete user script = /usr/sbin/smbldap-userdel "%u" add machine script = /usr/sbin/smbldap-useradd -w "%u" add group script = /usr/sbin/smbldap-groupadd -p "%g" delete group script = /usr/sbin/smbldap-groupdel "%g" add user to group script = /usr/sbin/smbldap-groupmod -m "%u" "%g" delete user from group script = /usr/sbin/smbldap-groupmod -x "%u" "%g" set primary group script = /usr/sbin/smbldap-usermod -g "%g" "%u" domain logons = yes # # End: Custom LDAP Entries # ##################################################### #STOP COPYING HERE! #####################################################
# Comment out the line:
invalid users = root
# Add the following line:
logon path =
# Restart SAMBA.
/etc/init.d/samba restart
# Give SAMBA the "admin" password to the LDAP tree.
smbpasswd -w 12345
Step 6: Configure the SMBLDAP-TOOLS package.
We will be using the smbldap-tools package to populate our directory, add users, add workstations, etc... But, the tools need to be configured first!
# Open up the examples directory.
cd /usr/share/doc/smbldap-tools/examples/
# Copy the configuration files to /etc/smbldap-tools:
cp smbldap_bind.conf /etc/smbldap-tools/
cp smbldap.conf.gz /etc/smbldap-tools/
# Unzip the configuration file.
gzip -d /etc/smbldap-tools/smbldap.conf.gz
# Open up the /etc/smbldap-tools directory.
cd /etc/smbldap-tools/
# Get the SID (Security ID) for your SAMBA domain.
net getlocalsid
This results in (example): SID for domain DC01-UBUNTU is: S-1-5-21-949328747-3404738746-3052206637
# Open the /etc/smbldap-tools/smbldap.conf file for editing.
vim smbldap.conf
# Edit the file so that the following information is correct (according to your individual setup):
SID="S-1-5-21-949328747-3404738746-3052206637" ## This line must have the same SID as when you ran "net getlocalsid"
sambaDomain="EXAMPLE"
ldapTLS="0"
suffix="dc=example,dc=local"
sambaUnixIdPooldn="sambaDomainName=EXAMPLE,${suffix}"
userSmbHome=
userProfile=
userHomeDrive=
userScript=
mailDomain="example.local"
# Open the /etc/smbldap-tools/smbldap_bind.conf file for editing.
vim smbldap_bind.conf
# Edit the file so that the following information is correct (according to your individual setup):
slaveDN="cn=admin,dc=example,dc=local" slavePw="12345" masterDN="cn=admin,dc=example,dc=local" masterPw="12345"
# Set the correct permissions on the above files:
chmod 0644 /etc/smbldap-tools/smbldap.conf
chmod 0600 /etc/smbldap-tools/smbldap_bind.conf
Step 7: Populate LDAP using smbldap-tools
Now we need to populate our LDAP directory with some necessary SAMBA and Windows entries.
# Execute the command to populate the directory.
smbldap-populate -u 30000 -g 30000
# At the password prompt assign your root password:
12345
# Verify that the directory has information in it by running the command:
ldapsearch -x -b dc=example,dc=local | less
Step 8: Add an LDAP user to the system
It is time for us to add an LDAP user. We will use this user account to verify that LDAP authentication is working.
# Add the user to LDAP
smbldap-useradd -a -m -M ricky -c "Richard M" ricky
# Here is an explanation of the command switches that we used.
-a allows Windows as well as Linux login
-m makes a home directory, leave this off if you do not need local access
-M sets up the username part of their email address
-c specifies their full name
# Set the password the new account.
smbldap-passwd ricky
# Password will be: 12345
Step 9: Configure the server to use LDAP authentication.
The basic steps for this section came from the Ubuntu Forums (http://ubuntuforums.org/showthread.php?t=597056). Thanks to all who contributed to that thread! Basically we need to tell our server to use LDAP authentication as one of its options. Be careful with this! It can cause your server to break! This is why we always have a backup around.
# Install the necessary software for this to work.
apt-get install auth-client-config libpam-ldap libnss-ldap
# Answer the prompts on your screen with the following:
Should debconf manage LDAP configuration?: Yes
LDAP server Uniform Resource Identifier: ldapi://127.0.0.1
Distinguished name of the search base: dc=example,dc=local
LDAP version to use: 3
Make local root Database admin: Yes
Does the LDAP database require login? No
LDAP account for root: cn=admin,dc=example,dc=local
LDAP root account password: 12345
# Open the /etc/ldap.conf file for editing.
vim /etc/ldap.conf
# Configure the following according to your setup:
host 127.0.0.1 base dc=example,dc=local uri ldap://127.0.0.1/ rootbinddn cn=admin,dc=example,dc=local bind_policy soft
# Copy the /etc/ldap.conf file to /etc/ldap/ldap.conf
cp /etc/ldap.conf /etc/ldap/ldap.conf
# Create a new file /etc/auth-client-config/profile.d/open_ldap:
vim /etc/auth-client-config/profile.d/open_ldap
# Insert the following into that new file:
[open_ldap] nss_passwd=passwd: compat ldap nss_group=group: compat ldap nss_shadow=shadow: compat ldap pam_auth=auth required pam_env.so auth sufficient pam_unix.so likeauth nullok auth sufficient pam_ldap.so use_first_pass auth required pam_deny.so pam_account=account sufficient pam_unix.so account sufficient pam_ldap.so account required pam_deny.so pam_password=password sufficient pam_unix.so nullok md5 shadow use_authtok password sufficient pam_ldap.so use_first_pass password required pam_deny.so pam_session=session required pam_limits.so session required pam_mkhomedir.so skel=/etc/skel/ session required pam_unix.so session optional pam_ldap.so
# Backup the /etc/nsswitch.conf file:
cp /etc/nsswitch.conf /etc/nsswitch.conf.original
# Backup the /etc/pam.d/ files:
cd /etc/pam.d/
mkdir bkup
cp * bkup/
# Enable the new LDAP Authentication Profile by executing the following command:
auth-client-config -a -p open_ldap
# Reboot the server and test to ensure that you can still log in using SSH and LDAP.
reboot
Step 10: Install BIND (DNS Server)
Because we are going to be a domain controller and source for authentication it makes sense to also have some DNS services available. Please note that if you have multiple servers at your disposal it is recommended to install a seperate DNS server as well so we have two to look at.
# Install the software.
apt-get install bind9
Step 11: Configure our primary DNS Zone using WebMin
We now want to create our DNS zone so that we are in charge of it and can make use of it. I prefer using a GUI to do this as opposed to editing the zone files.
In a web browser navigate to: https://192.168.0.60:10000 (Please use the IP address that YOU assigned to your server.)
Login as "sysadmin" and "12345".
Servers > BIND DNS Server
Under "Existing DNS Zones" click "Create master zone".
Zone type: Forward (Names to Addresses)
Domain name / Network: example.local
Records file: Automatic
Master server: dc01-ubuntu.example.local
Email address: sysadmin@example.local
Click "Create" button.
Click "Apply Changes" button.
Click "Address (0)" at the top.
Name: dc01-ubuntu
Address: 192.168.0.60
Click "Create" button
Click "Return to record types"
Click "Apply Changes" button.
Step 12: Configure the server to use itself for DNS
DNS doesn't do a whole lot of good if we don't use it. In this section we point our /etc/resolv.conf file to ourselves. I also recommend leaving in a known working DNS server as the seconday source just in case something screws up. In some of my trials I did notice that the server would hang trying to start BIND9.
# Open the /etc/resolv.conf file for editing.
vim /etc/resolv.conf
# Add the following lines to the beginning of the file:
search example.local nameserver 192.168.0.60
# Reboot the server to ensure that DNS is working correctly.
reboot
Step 13: Add a workstation account to LDAP
This tutorial is meant to create an opensource domain for Windows XP Professional client (and Linux clients) to authenticate against. Therefore we will add a workstation account for the Windows XP Professional workstation that we will be joining to the domain.
# Execute the command:
smbldap-useradd -w client-winxp
* "client-winxp" is the hostname of the computer that you will be adding to the domain. This must be very specific!
Step 14: Configure your Windows XP Professional Client
Now I will walk you through configuring your Windows XP Professional workstation so that it will join the domain.
# Assumptions:
* This is a vanilla installation of Windows XP Professional SP2.
* The computer name was set during installation to be: client-winxp
* The Administrator password assigned is: 12345
* All other installation options have been left at their default settings.
* After the installation the following occurred:
* The only user account on the computer in use was "Administrator"
* All available Windows Updates were installed.
* A static IP address was assigned with the following information (for my setup only!)
IP Address: 192.168.0.61
Gateway: 192.168.0.1
Netmask: 255.255.255.0
DNS: 192.168.0.60
Search domain: example.local
# Join the workstation to the domain.
* Log into the computer as Administrator.
* Right click "My Computer" and click "Properties".
* Click the tab "Computer Name".
* Click the button labeled "Change".
* At the bottom click the radial button labeled "Domain".
* In the box type the word "example" without quotes!
* Click the "OK" button.
* At the password prompt enter "root" for the user and "12345" for the password (substitute the password for what you assigned to your root user earlier!).
It should say "Welcome to the example domain."
* Click "OK".
* Click "OK" again.
* Click "OK" again.
Restart the workstation.
# Log in with your test user ("ricky") from earlier.
Try logging into the Windows XP workstation (after selecting the domain from the drop down box) using our test user. It should work without issue!
# Notes
Please note that this is basic authentication right now. You're on your own if you wish to add logon scripts, mapped drives, etc...
Step 15: (Optional) Install Apache2 and PHPLDAPAdmin
A nice way to view and modify your LDAP tree is with a GUI. PHPLDAPAdmin is one that many people recommend so I will show you how to install it and use it.
# Install the software.
apt-get install apache2 phpldapadmin
# Open the file /etc/apache2/httpd.conf for editing:
vim /etc/apache2/httpd.conf
# Add the following line to the top of the file. This prevents an annoying error message from Apache2.
ServerName dc01-ubuntu.example.local
# Restart Apache2
/etc/init.d/apache2 restart
# Copy the PHPLDAPAdmin folder into the main web site directory. This is the lazy way of doing things. This way we don't need to create a virtual server, we just access PHPLDAPAdmin by going to: http://192.168.0.60/phpldapadmin/
cp -R /usr/share/phpldapadmin/ /var/www/phpldapadmin
There you have it! A full Ubuntu LDAP and SAMBA Domain Controller in 15 easy steps.
Feeding entropy to GnuPG on Fedora
From: Aaron S. Hawley (http://aaronhawley.livejournal.com/10807.html)
In a previous post, I mentioned we are putting together an RPM build server at work. The RPMs that are built are signed by an encryption key and uploaded to the Yum server. The GnuPG (GPG) signing will give us confidence that the RPMs were from the build server and weren't tampered with since they were built and copied to the Yum repository.
At this point, the security of the signing key is not important. I say this confidently even after the recent package signing compromise at Fedora and Red Hat. We want to have automated package signing and we're only building packages for distribution inside the office.
One nice feature of GnuPG is its automatic key generation. The RPM build server is generating its own key, and preferably as non-interactive as possible. Unfortunately, this requires entropy to work consistently.
For information about automatically generating keys with GPG see the section "Unattended key generation" in the DETAILS file that comes with GnuPG. That documentation can be found on a GNU/Linux system with the following command.
$ less -p "^Unattended" /usr/share/doc/gnupg-*/DETAILS
As the summary says:
This feature allows unattended generation of keys controlled by a parameter file. To use this feature, you use --gen-key together with --batch and feed the parameters either from stdin or from a file given on the command line [sic].
Here's an example of automatically generating a secret GPG key.
$ cat gpg-key.conf
%echo Generating a package signing key
Key-Type: DSA
Key-Length: 1024
Subkey-Type: ELG-E
Subkey-Length: 2048
Name-Real: Build Server
Name-Email: builds@site.org
Expire-Date: 0
Passphrase: Does not ex1st!
%commit
%echo Done
$ gpg --batch --gen-key gpg-key.conf \
> gpg-keygen.log \
2> gpg-keygen_error.log
Those familliar with generating keys know that it is an extremely interactive process. Not just for entering the details about the key, but because you need to inject entropy into the computer to ensure the newly generated key is random. (Debian had erroneously weakened the random number generation in a security-related package necessitating a significant response to those systems affected by the vulnerability.) Usually, GnuPG receives entropy by jiggling the mouse or banging on the keyboard. As the GnuPG README says:
If you see no progress during key generation you should start some other activities such as moving the mouse or hitting the CTRL and SHIFT keys. Generate a key only on a machine where you have direct physical access - don't do it over the network or on a machine also used by others, especially if you have no access to the root account. (original emphasis)
This becomes a problem on servers that don't have mice or keyboards attached. One would typically see the following message from GnuPG complaining about not having enough entropy.
$ gpg --batch --gen-key gpg-key.conf gpg: Generating a package signing key .++++++++++++++++++++...+++++..++++++++++++++++++++++++++++++++++++++++++++++++ +++++++.+++++++++++++++++++++++++++++++++++++++++++++++++++++++..>+++++...+++++ Not enough random bytes available. Please do some other work to give the OS a chance to collect more entropy! (Need 123 more bytes) gpg: Interrupt caught ... exiting
As a sidebar, the "Key generation" section of the DETAILS file explains all those special characters spit to the screen when the key is generated.
Key generation shows progress by printing different characters to
stderr:
"." Last 10 Miller-Rabin tests failed
"+" Miller-Rabin test succeeded
"!" Reloading the pool with fresh prime numbers
"^" Checking a new value for the generator
"<" Size of one factor decreased
">" Size of one factor increased
I tried various complicated strategies of creating entropy on a headless system to no success. One of them was piping the output of /dev/random into /dev/urandom and visa verse. Let's see if I can rehash it here.
$ b=2048; \
future=$(date -d'+6 seconds' +'%s' ); \
while [ ${future} -gt $(date +'%s') ]; do \
head -c b /dev/random > /dev/urandom; \
head -c ${b} /dev/urandom > /dev/random; \
done &
$ gpg --batch --gen-key gpg-key.conf
Anyway, it didn't work.
Running this does, though.
# rngd -r /dev/urandom
The rngd service provides "true random number generation" (RNG). It comes as part of the rng-tools package.
According to the documentation in the Linux kernel:
The hw_random framework is software that makes use of a special hardware feature on your CPU or motherboard, a Random Number Generator (RNG). The software has two parts: a core providing the /dev/hw_random character device and its sysfs support, plus a hardware-specific driver that plugs into that core.
In Fedora, this package can be installed with Yum.
# yum install rng-utils
I've arrived on Planet Fedora. Planet Fedora is an aggregation of article feeds from members of the Fedora Project -- a community project affiliated with Red Hat that distributes the GNU/Linux operating system.
How to remove the gdm user list in Ubuntu 10.04
Put the following in /var/lib/gdm/.gconf/apps/gdm/simple-greeter/%gconf.xml:
<?xml version="1.0"?> <gconf> <entry name="recent-layouts" mtime="1276112027" type="list" ltype="string"> <li type="string"> <stringvalue>br</stringvalue> </li> </entry> <entry name="recent-languages" mtime="1276112026" type="list" ltype="string"> <li type="string"> <stringvalue>pt_BR.utf8</stringvalue> </li> </entry> <entry name="disable_user_list" mtime="1227900586" type="bool" value="true"> </entry> </gconf>
Setting Up A High-Availability Load Balancer (With Failover and Session Support) With HAProxy/Keepalived On Debian Etch
Version 1.0
Author: Falko Timme <ft [at] falkotimme [dot] com>
Last edited 10/16/2007
This article explains how to set up a two-node load balancer in an active/passive configuration with HAProxy and keepalived on Debian Etch. The load balancer sits between the user and two (or more) backend Apache web servers that hold the same content. Not only does the load balancer distribute the requests to the two backend Apache servers, it also checks the health of the backend servers. If one of them is down, all requests will automatically be redirected to the remaining backend server. In addition to that, the two load balancer nodes monitor each other using keepalived, and if the master fails, the slave becomes the master, which means the users will not notice any disruption of the service. HAProxy is session-aware, which means you can use it with any web application that makes use of sessions (such as forums, shopping carts, etc.).
From the HAProxy web site: "HAProxy is a free, very fast and reliable solution offering high availability, load balancing, and proxying for TCP and HTTP-based applications. It is particularly suited for web sites crawling under very high loads while needing persistence or Layer7 processing. Supporting tens of thousands of connections is clearly realistic with todays hardware. Its mode of operation makes its integration into existing architectures very easy and riskless, while still offering the possibility not to expose fragile web servers to the Net."
I do not issue any guarantee that this will work for you!
1 Preliminary Note
In this tutorial I will use the following hosts:
- Load Balancer 1: lb1.example.com, IP address: 192.168.0.100
- Load Balancer 2: lb2.example.com, IP address: 192.168.0.101
- Web Server 1: http1.example.com, IP address: 192.168.0.102
- Web Server 2: http2.example.com, IP address: 192.168.0.103
- We also need a virtual IP address that floats between lb1 and lb2: 192.168.0.99
Here's a little diagram that shows our setup:
shared IP=192.168.0.99
192.168.0.100 192.168.0.101 192.168.0.102 192.168.0.103
-------+------------+--------------+-----------+----------
| | | |
+--+--+ +--+--+ +----+----+ +----+----+
| lb1 | | lb2 | | http1 | | http2 |
+-----+ +-----+ +---------+ +---------+
haproxy haproxy 2 web servers (Apache)
keepalived keepalived
The shared (virtual) IP address is no problem as long as you're in your own LAN where you can assign IP addresses as you like. However, if you want to use this setup with public IP addresses, you need to find a hoster where you can rent two servers (the load balancer nodes) in the same subnet; you can then use a free IP address in this subnet for the virtual IP address. Here in Germany, Hetzner is a hoster that allows you to do this - just talk to them. Update: Hetzner's policies have changed - please read here for more details: http://www.howtoforge.com/forums/showthread.php?t=19988
http1 and http2 are standard Debian Etch Apache setups with the document root /var/www (the configuration of this default vhost is stored in /etc/apache2/sites-available/default). If your document root differs, you might have to adjust this guide a bit.
To demonstrate the session-awareness of HAProxy, I'm assuming that the web application that is installed on http1 and http2 uses the session id JSESSIONID.
2 Preparing The Backend Web Servers
We will configure HAProxy as a transparent proxy, i.e., it will pass on the original user's IP address in a field called X-Forwarded-For to the backend web servers. Of course, the backend web servers should log the original user's IP address in their access logs instead of the IP addresses of our load balancers. Therefore we must modify the LogFormat line in /etc/apache2/apache2.conf and replace %h with %{X-Forwarded-For}i:
http1/http2:
vi /etc/apache2/apache2.conf
[...]
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[...]
|
Also, we will configure HAProxy to check the backend servers' health by continuously requesting the file check.txt (translates to /var/www/check.txt if /var/www is your document root) from the backend servers. Of course, these requests would totally bloat the access logs and mess up your page view statistics (if you use a tool like Webalizer or AWstats that generates statistics based on the access logs).
Therefore we open our vhost configuration (in this example it's in /etc/apache2/sites-available/default) and put these two lines into it (comment out all other CustomLog directives in your vhost configuration):
vi /etc/apache2/sites-available/default
[...] SetEnvIf Request_URI "^/check\.txt$" dontlog CustomLog /var/log/apache2/access.log combined env=!dontlog [...] |
This configuration prevents that requests to check.txt get logged in Apache's access log.
Afterwards we restart Apache:
/etc/init.d/apache2 restart
... and create the file check.txt (this can be an empty file):
touch /var/www/check.txt
We are finished already with the backend servers; the rest of the configuration happens on the two load balancer nodes.
3 Installing HAProxy
Unfortunately HAProxy is available as a Debian package for Debian Lenny (testing) and Sid (unstable), but not for Etch. Therefore we will install the HAProxy package from Lenny. To do this, open /etc/apt/sources.list and add the line deb http://ftp2.de.debian.org/debian/ lenny main; your /etc/apt/sources.list could then look like this:
lb1/lb2:
vi /etc/apt/sources.list
deb http://ftp2.de.debian.org/debian/ etch main deb-src http://ftp2.de.debian.org/debian/ etch main deb http://ftp2.de.debian.org/debian/ lenny main deb http://security.debian.org/ etch/updates main contrib deb-src http://security.debian.org/ etch/updates main contrib |
Of course (in order not to mess up our system), we want to install packages from Lenny only if there's no appropriate package from Etch - if there are packages from Etch and Lenny, we want to install the one from Etch. To do this, we give packages from Etch a higher priority in /etc/apt/preferences:
vi /etc/apt/preferences
Package: * Pin: release a=etch Pin-Priority: 700 Package: * Pin: release a=lenny Pin-Priority: 650 |
(The terms etch and lenny refer to the appropriate terms in /etc/apt/sources.list; if you're using stable and testing there, you must use stable and testing instead of etch and lenny in /etc/apt/preferences as well.)
Afterwards, we update our packages database:
apt-get update
... upgrade the installed packages:
apt-get upgrade
... and install HAProxy:
apt-get install haproxy
4 Configuring The Load Balancers
The HAProxy configuration is stored in /etc/haproxy.cfg and is pretty straight-forward. I won't explain all the directives here; to learn more about all options, please read http://haproxy.1wt.eu/download/1.3/doc/haproxy-en.txt and http://haproxy.1wt.eu/download/1.2/doc/architecture.txt.
We back up the original /etc/haproxy.cfg and create a new one like this:
lb1/lb2:
cp /etc/haproxy.cfg /etc/haproxy.cfg_orig
cat /dev/null > /etc/haproxy.cfg
vi /etc/haproxy.cfg
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
#log loghost local0 info
maxconn 4096
#debug
#quiet
user haproxy
group haproxy
defaults
log global
mode http
option httplog
option dontlognull
retries 3
redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen webfarm 192.168.0.99:80
mode http
stats enable
stats auth someuser:somepassword
balance roundrobin
cookie JSESSIONID prefix
option httpclose
option forwardfor
option httpchk HEAD /check.txt HTTP/1.0
server webA 192.168.0.102:80 cookie A check
server webB 192.168.0.103:80 cookie B check
|
Afterwards, we set ENABLED to 1 in /etc/default/haproxy:
vi /etc/default/haproxy
# Set ENABLED to 1 if you want the init script to start haproxy. ENABLED=1 # Add extra flags here. #EXTRAOPTS="-de -m 16" |
5 Setting Up keepalived
We've just configured HAProxy to listen on the virtual IP address 192.168.0.99, but someone has to tell lb1 and lb2 that they should listen on that IP address. This is done by keepalived which we install like this:
lb1/lb2:
apt-get install keepalived
To allow HAProxy to bind to the shared IP address, we add the following line to /etc/sysctl.conf:
vi /etc/sysctl.conf
[...] net.ipv4.ip_nonlocal_bind=1 |
... and run:
sysctl -p
Next we must configure keepalived (this is done through the configuration file /etc/keepalived/keepalived.conf). I want lb1 to be the active (or master) load balancer, so we use this configuration on lb1:
lb1:
vi /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
script "killall -0 haproxy" # cheaper than pidof
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 101 # 101 on master, 100 on backup
virtual_ipaddress {
192.168.0.99
}
track_script {
chk_haproxy
}
}
|
(It is important that you use priority 101 in the above file - this makes lb1 the master!)
Then we start keepalived on lb1:
lb1:
/etc/init.d/keepalived start
Then run:
lb1:
ip addr sh eth0
... and you should find that lb1 is now listening on the shared IP address, too:
lb1:/etc/keepalived# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:a5:5b:93 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.100/24 brd 192.168.0.255 scope global eth0
inet 192.168.0.99/32 scope global eth0
inet6 fe80::20c:29ff:fea5:5b93/64 scope link
valid_lft forever preferred_lft forever
lb1:/etc/keepalived#
Now we do almost the same on lb2. There's one small, but important difference - we use priority 100 instead of priority 101 in /etc/keepalived/keepalived.conf which makes lb2 the passive (slave or hot-standby) load balancer:
lb2:
vi /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
script "killall -0 haproxy" # cheaper than pidof
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_1 {
interface eth0
state MASTER
virtual_router_id 51
priority 100 # 101 on master, 100 on backup
virtual_ipaddress {
192.168.0.99
}
track_script {
chk_haproxy
}
}
|
Then we start keepalived:
lb2:
/etc/init.d/keepalived start
As lb2 is the passive load balancer, it should not be listening on the virtual IP address as long as lb1 is up. We can check that with:
lb2:
ip addr sh eth0
The output should look like this:
lb2:~# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:e0:78:92 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.101/24 brd 192.168.0.255 scope global eth0
inet6 fe80::20c:29ff:fee0:7892/64 scope link
valid_lft forever preferred_lft forever
lb2:~#
6 Starting HAProxy
Now we can start HAProxy:
lb1/lb2:
/etc/init.d/haproxy start
7 Testing
Our high-availability load balancer is now up and running.
You can now make HTTP requests to the virtual IP address 192.168.0.99 (or to any domain/hostname that is pointing to the virtual IP address), and you should get content from the backend web servers.
You can test its high-availability/failover capabilities by switching off one backend web server - the load balancer should then redirect all requests to the remaining backend web server. Afterwards, switch off the active load balancer (lb1) - lb2 should take over immediately. You can check that by running:
lb2:
ip addr sh eth0
You should now see the virtual IP address in the output on lb2:
lb2:~# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:e0:78:92 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.101/24 brd 192.168.0.255 scope global eth0
inet 192.168.0.99/32 scope global eth0
inet6 fe80::20c:29ff:fee0:7892/64 scope link
valid_lft forever preferred_lft forever
lb2:~#
When lb1 comes up again, it will take over the master role again.
8 HAProxy Statistics
You might have noticed that we have used the options stats enable and stats auth someuser:somepassword in the HAProxy configuration in chapter 4. This allow us to access (password-protected) HAProxy statistics under the URL http://192.168.0.99/haproxy?stats. This is how it looks:
If you don't need the statistics, just comment out or remove the stats lines from the HAProxy configuration.
9 Links
- HAProxy: http://haproxy.1wt.eu
- Keepalived: http://www.keepalived.org
- Debian: http://www.debian.org
NoSurf
from: http://gutocarvalho.net/mediawiki/index.php?title=Lendo_Log_do_SNORT_para_bloquear_UltraSurf
NoSurf
De gutocarvalho.net
Este mês o Sr. Augusto Ferronato publicou na SNORT-BR uma regra criada pela equipe de segurança do SERPRO-RECIFE que detecta o uso do ULTRASURF. A equipe do SERPRO fez um tracing nas conexões do ultrasurf e identificou que um dos comportamentos do programa era o envio de uma requisição DNS para servidores externos com um pacote com o tamanho de 554 bytes, sendo 480 bytes desdes com valor igual a 0.
snort rule
A regra é esta baixo, lembre-se não tem as quebras de linha, é tudo numa linha só
alert udp $HOME_NET any -> !$HOME_NET 53 (msg: "[OSSEC] Consulta de DNS Externo Possivel Ultrasurf"; content:"|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|"; classtype: policy-violation;threshold:type limit, track by_src,count 1, seconds 5;sid: 1000059; rev:2; )
com esta regra, caso o snorte fareje algo que case com ela, emitirá um altera que terá uma saída como:
"[OSSEC] Consulta de DNS Externo Possivel Ultrasurf", 08/27-14:30:09.728544 ,192.168.0.1 ,218.153.6.52 ,53
noSurf.sh
o script abaixo lê o log do snort capturando o endereço IP para bloqueio via netfilter.
vamos usar o vim para criar o script
root@servidor:~# vim noSurf.sh
#!/bin/bash
# caminho para log do snort
a0="snort.log"
# local para arquivos temporarios
apath="/tmp"
# arquivos temporarios
a1="$apath/snort_list.txt"
a2="$apath/netfilter_list.txt"
a3="$apath/blocked_ips.txt"
a4="$apath/noSurf_alerta.txt"
function geraListaSnort()
{
> $a1
for i in `cat $a0 |awk '{ print $9 }'|sed 's/,//'`;do
echo $i >> $a1
done
}
function geraListaIptables()
{
> $a2
for i in `iptables -nvL INPUT|grep DROP|awk '{ print $8 }'`;do
echo $i >> $a2
done
}
function bloqueiaIp()
{
for i in `cat $a3`;do
echo bloqueando o endereco ip: $i
iptables -t filter -I INPUT -s $i -j DROP
done
}
function enviaAlerta()
{
echo -e "O enderecos IP abaixo foram bloqueados por possivel utilizacao de ultrasurf:\n" | tee -a $a4
for i in `cat $a3`;do
echo $i | tee -a $a4
done
mail -s "noSurf report" seuemail@seuprovedor.com.br < $a4
}
function comparaListas()
{
> $a3
> $a4
for i in `cat $a1|sort -u`;do
cat $a2|grep $i > /dev/null
if [ $? == 0 ];then
echo o endereco ip $i ja esta bloqueado na firewall.
else
echo o endereco ip $i nao esta bloqueado na firewall.
echo $i >> $a3
fi
done
bloqueiaIp
enviaAlerta
rm -f $a1
rm -f $a2
rm -f $a3
rm -f $a4
}
# executando funcoes do script
geraListaSnort
geraListaIptables
comparaListas
agora vamos ajustar as permissões
root@servidor:~# chmod 700 noSurf.sh
você pode colocar este script no CRON para ser executado periódicamente.
Setting Up A Snort IDS on Debian Linux
from: http://www.aboutdebian.com/snort.htm
Setting Up A Snort IDS on Debian Linux
![]()
The material on this page was prepared using Lenny
configured using our Installation and Packages pages.
If you did not use our pages to set up your system, what you
encounter on your system may be different than what is given here.
Malicious network traffic (such as worms, hacking attempts, etc.) has certain patterns to it. You could monitor your network traffic with a sniffer and look for this malicious traffic manually but that would be an impossible task. Enter IDS (Intrusion Detection System) software which automates the process of sniffing, examining, and upon finding something suspicious, alerting.
IDS has been called the burglar alarm of computer networks and is an important part of network perimeter security. WIthout an IDS you have no idea if someone is probing or attacking your servers (unless the attack is so overwhelming that it results in a denial of service). Having this information can let you know if you need to make some firewall changes or harden the OS on a particular server a bit more.
You may see the term IPS for Intrusion Prevention Systems which takes things one step further, having the IDS adjust the firewall when it discovers something. Smart people disagree on the use of IPSs as it, in effect, gives an attacker some control of your firewall.
Snort (www.snort.org) is the most widely-used IDS software applicaton and it's open source and included with Debian. There are two flavors of IDSs, host-based and network-based. Snort is a network-based IDS that can monitor all of the traffic on a network link to look for suspicious traffic. Typically, a network-based IDS is set up to monitor a DMZ or the internal network right behind the firewall so it alerts to any possible threats that your firewall didn't catch.
There is a Web interface that works with Snort called BASE (Basic Analysis and Security Engine) which is based on ACID (Analysis Console for Intrusion Databases) which we'll set up. BASE uses what's commonly referred to as a LAMP server (Linux, Apache, MySQL, PHP) so we'll need to install those applications as well.
Because LAMP servers tend to attract hackers we'll want to put the Snort box on an internal network but this requires setting up your Snort box with two NICs. One NIC is connected to your internal network with an appropriate IP address for that network (like 172.24.1.20). This internal address is the one we point our Web browsers at when we want to look at the BASE Web pages. The other NIC does NOT have an IP address. It plugs into whatever network segment you want to monitor, like your DMZ or even your Interent segment outside of your firewall. Snort puts this NIC into promiscuous mode so it can snort up all the traffic it sees (basically it's Snort's snout). By not putting an IP address on Snort's promiscuous NIC you can get away with plugging this NIC into a DMZ link or even outside of your firewall (on your Internet link).
On this page we assigned an address to the eth0 interface and we'll be using eth1 as the promiscuous interface. Adjust these values for your system as necessary.
If you run the Debian installer with two NICs installed in the system, it will let you choose if you want to configure eth0 or eth1 with an IP address. However, this necessitates that you use the netcfg/disable_dhcp=true switch when you start the Debian installation. (We specify using this switch on our Installation page.) If you have more than one brand of NIC to choose from it'll make your life a little easier if you use NICs by two different manufacturers as it will be easier to determine which NIC Debian designates as the eth0 interface and which NIC is designated as the eth1 interface.
Connecting the promiscuous NIC into the segment you want to monitor is not as easy as just plugging it into a switch port. Because switches segment each port into it's own little collision domain, if you do plug the promiscuous NIC into a switch port it'll only see broadcast traffic. You need to either tap into the link you want to monitor using a hub, or you have to do port spanning on your switch. If you're interested in monitoring traffic coming in from the Internet, given that most Internet (broadband) connections are less than 10 megabit you can pick up an old 4-port 10-meg hub on eBay to tap into this link. (Just make sure you're getting a hub as many people use the terms hub and switch interchangeably.) If you want to monitor traffic on your internal network, you could configure port spanning on your switch. Port spanning simply takes all of the traffic on one or more switch ports and duplicates it to a span port that has a monitoring device connected. Consult your switch documentation on how to set this up.
![]()
The above diagram shows how you'd use a hub to monitor the traffic coming in from a cable or DSL modem. Note that Snort's promiscuous NIC is located before the cable/DSL router. (Most cable/DSL routers have some limited firewall capabilities.) In this case, in order to determine the HOME_NET value (discussed below) you'd have to know the IP address that your router pulled from your ISP's DHCP server. The easiest way to find out what IP address your router pulled is to visit a Web site like whatsmyipaddress.com that displays your "external" IP address when you visit the site.NOTE: There's no law saying that both NICs can't be connected to the same network (even the same switch). If you wanted to monitor your internal network for possible virus or worm traffic, both NICs would be connected to the same network. The promiscuous NIC would be connected to a span port sucking up the traffic and the addressed NIC is used for accessing the BASE Web pages.
Snort has a "rule base" that contains patterns or "signatures" of malicious traffic much like an antivirus program has a database of virus signatures that it uses to compare to streams of program code. Also like antivirus software, you can download updates to Snort's rule base file. Unlike an antivirus signature database, you can tweak the rules in Snort's rule base to minimize false alerts. You can also choose which rules you want Snort to use and which to ignore to taylor Snort to your network environment. For example, a Snort rule may closely resemble the traffic patterns of a custom-written Web application that your organization uses. In this case you would disable this rule so you don't get false-positive alerts when the application is used.
Installing Snort Lets start setting up the LAMP server by intalling MySQL with the command:
apt-get install mysql-server
You'll be prompted to enter a password for the MySQL root account (equivalent to the sa password in MS SQL). We'll be needing it in a few minutes. If you haven't already done so, install Apache next with the command:
apt-get install apache2
Now finish the LAMP server setup with the command:
apt-get install php5
Now that we have our LAMP server components installed we can install Snort. Because we have MySQL installed we can use the MySQL-specific Snort (version 2.7) package.
What Is HOME_NET ? The HOME_NET variable in Snort's configuration file should contain (in CIDR format) the network that you want to protect, i.e. the network that your servers are on, i.e. the network you are going to plug the promiscuous NIC into. This may not be the same network that the addressed NIC on your Snort box plugs into.
Install the package with the command:
apt-get install snort-mysql
The first thing it asks for is the HOME_NET value. If your servers are on a Class C network (or subnet) with an address like 192.168.1.15 then enter 192.168.1.0/24 for the HOME_NET CIDR block. If your servers are on a Class B network with an address of something like 172.24.3.15 then enter 172.24.0.0/16 for the HOME_NET CIDR block. In our diagram above, lets say your router pulled an IP address of 64.233.161.147. You could just enter that as a Class C CIDR block of 64.233.161.0/24.The next screen tells you that no database has been set up for Snort. Press Enter and then, with the default Yes selected, press Enter again.
Snort will finish installing and it will end with an error (error code 1). That error was generated because Snort failed to start. Snort failed to start because it's not configured yet. In short, no problem.
Next we'll install the BASE Web interface with the command:
apt-get install acidbase
You'll see an informational screen about the include path (just press Enter) and a manual configuration informational screen (just press Enter.)Next you'll be prompted to configure the database for acidbase. Select the default 'Yes' by pressing Enter. Then on the next screen 'mysql' will be selected so just press Enter.
Next you'll be prompted to enter the password for the MySQL "administrative user" which is root so enter the MySQL root password that you entered above when you installed MySQL.
You'll then be prompted to create and confirm an application password for the acidbase database. Note that this is not the password for the MySQL root account you just entered. This password should not be the same as your MySQL root password because it's stored in clear text. Once these are entered the acidbase installation will finish. (You'll get the snort-mysql error code 1 again but don't worry about it for now.)
The next thing we have to do is alias the BASE directory to our Apache "Web root" so we can include it in a browser URL. To do that we need to enter some statements into the Apache default configuration file. Luckily the statements we need to enter are in a file that was installed with the acidbase package. Open the Apache default configuration file with the command:
nano /etc/apache2/sites-available/default
Cursor down to the bottom of the file. The last line in the file is the </VirtualHost> statement. Put your cursor on the blank line just above this statement and press Ctrl-r and in the "File to insert" field enter:
/etc/acidbase/apache.conf
and press Enter. Cursor up a few lines to the line that reads:
allow from 127.0.0.0/255.0.0.0
and change the network address and subnet mask to match the machines on your local network that will be accessing the BASE Web pages. For example, change it to 192.168.1.0/255.255.255.0 for a Class C internal network. You can change both the address and subnet mask to all zeros if you want don't want any address restrictions on who can access the BASE Web pages.Now do a Ctrl-x and press 'y' at the prompt to save the changes and press Enter to write the file.
During the acidbase installation we were prompted to create a Snort database. However, now we have to use a pre-defined script to build the structure (tables, fields, etc.) of the database. Change directories with the command:
cd /usr/share/doc/snort-mysql
and enter the following command to run a script which creates the database structure. Note that that is a pipe symbol after create_mysql.gz in the command. Also note that you want to enter the application password that you entered during the acidbase install, not the MySQL root password. If you don't remember what you entered, cat the /etc/acidbase/database.php file. Also be sure to NOT put a space between the -p and the password itself.
zcat create_mysql.gz | mysql -u snort -D snort -papplicationpassword
If you don't see anything be glad. The only time executing this command will print out anything is if there was an error. With the database configured Snort can now start. However, there is a 'flag' file that we need to delete to indicate that we have the database configured. Enter the command:
rm /etc/snort/db-pending-config
to delete this file. With that flag gone we need to do a little installation housekeeping with the command:
dpkg --configure --pending
Because our promiscuous NIC wasn't "up" when we installed Snort, it just assumed we wanted to use the NIC that was up. We need to tell Snort to use our promiscuous NIC. We do this by reconfiguring Snort with the command:
dpkg-reconfigure snort-mysql
For the "Snort start method" accept the default boot selection, tab to OK and press Enter.At the informational screen on interfaces, tab to OK and press Enter.
Assumming your promiscuous NIC is the second NIC in your system, change the interface value to eth1 instead of eth0 and then tab to OK and press Enter.
On the next screen the HOME_NET value you entered during the package installation should still be there (if not, re-enter it) so just tab to OK and press Enter.
Next you are asked if you want to disable promiscuous mode on the interface you entered. Accept the default No by pressing Enter.
Next you are asked if you want to change Snort's testing order. Accept the default No by pressing Enter.
Leave the "Additional custom options" field blank, tab to OK and press Enter.
Next you have the option of receiving daily summaries by e-mail. If you answer 'Yes' to this, and enter a recipient other than the default 'root' entry (be sure to enter a full e-mail address), see the section below on setting up e-mail services.
For now, accept the default value of 1 for minimum occurances by tabbing to OK and pressing Enter.
The next screen lets you know that Snort hasn't been set up to write entries to a database. Press Enter at OK and again at Yes to set this up.
When it asks for a "Database server hostname" enter localhost and tab to OK and press Enter.
Next it will ask you for the name of an existing database. Enter snort, tab to OK and press Enter.
In the "Username" field enter snort, tab to OK and press Enter.
In the "password" field enter the application password you chose earlier, tab to OK and press Enter. Then press Enter again at the information screen.
You'll see messages that Snort failed to start because eth1 was not available. We need to change the way Snort starts so it uses our promiscous NIC. Snort is set to run as a daemon automatically at boot up but with that configuration it won't bring up our promiscuous NIC (eth1). Disable this with the command:
mv /etc/rc2.d/S20snort /etc/rc2.d/_S20snort
We'll create a startup script of our own to bring up our promiscuous NIC and set it not to respond to arp requests (so hackers don't discover we're monitoring the network segment). Fire up a text editor with the command:
nano /etc/init.d/runsnort.sh
and enter the following two commands:
ifconfig eth1 up -arp
/etc/init.d/snort start
Exit the editor saving the file. Now we need to make our script executable with the command:
chmod 750 /etc/init.d/runsnort.sh
All scripts that could be run when the system boots, no matter the runlevel, are put in the /etc/init.d directory but it's the runlevel that determines which of these scripts actually gets run when the system boots up. Debian's default runlevel is 2 so we need to create a symbolic link to our script in the runlevel 2 directory. Do that with the command:
ln -s /etc/init.d/runsnort.sh /etc/rc2.d/S95runsnort
Reboot your system. Everything should now come up automatically. (When Snort starts it will indicate which NIC it's using.) Connect your promiscuous NIC to the network segement you want to montior, either by using a hub or spanning a switch port, and test it out.You can make sure the promiscuous NIC came up during the bootup process by entering the command:
ifconfig
The promiscuous NIC (eth1) should be listed and NOT have an "inet addr" (IP address) entry while the NIC you've assigned an IP address to should.Next, make sure Snort is seeing network traffic on the promiscuous NIC by entering the command:
snort -i eth1 -v
This will run a second instance of Snort in verbose mode. The destination IP addresses of the traffic displayed should be within the network address space of the HOME_NET value you specified earlier. Press Ctrl-C to stop the display and exit the second instance of Snort.We've got Snort up and running but there's still some minor BASE stuff we need to take care of. This next bit of setup is done via a Web browser. Get on another system on the network and fire up a browser (or fire up a browser on your Snort box if you installed the X-Windows and browser packages) and enter the following URL using the IP address you assigned to the addressed NIC of your Snort box:
http://172.16.1.52/acidbase/
You should see the BASE banner graphic and, right underneath it, a message saying that the database "appears to be incomplete/invalid." On the next line you'll see a Setup page link. Click on that.One the right side of the next page you'll see a Create BASE AG button. Click on that.
You should see a series of red Successfully created and Successfully INSERTED messages displayed. Further down on the left side of the page, click on the Main page link. This is the BASE home page and it will update automatically every three mintues.
What If Nothing Is Displayed Having all "0%" showing for the traffic graphs on the BASE home page is what we're hoping for (no suspicious traffic) but if nothing is ever displayed you may have a problem. The most common cause of the BASE Web pages never displaying any statistics or alert information when you know there should be is an incorrect HOME_NET value. Check to make sure the value you set for the HOME_NET variable matches the address space of the network segment you're monitoring.
Snort's default configuration file is the /etc/snort/snort.conf file. However, there is also a /etc/snort/snort.debian.conf file. The Debian-specific file is where the settings are stored when you run the dpkg-reconfigure command. This Debian-specific configuration file is used by the /etc/init.d/snort startup script and the settings in it take precedence over the corresponding settings in the /etc/snort/snort.conf file.Next we have to take care of setting up the summary e-mails that Snort sends out.
Setting Up Snort E-mailing If you answered 'No' to receiving summary e-mails from Snort or you accepted the default 'root' recipient, you can skip to the "Managing Rules" section.
By default, the Debian installer installs the Exim mail server package and configures it to only handle local (between accounts on the server) delivery. We need to set up our server to act as an e-mail client (like Outlook or Thunderbird) to your SMTP server so it can send the daily summary e-mails Snort generates to an "outside" (non-local) e-mail address.
We reconfigure Exim with the command:
dpkg-reconfigure exim4-config
Press Enter at the configuration information screen. On the configuration selection screen, because Snort won't be receiving any mail, select the "mail sent by smarthost; no local mail" option.Next it asks for a "system mail name". This should have the same domain name as your e-mail address. For example, if your e-mail address is fred@flinstone.com then your system mail name should be something like debian.flintstone.com (the first part of the name should be the hostname of your server and the second part would be your, or your ISP's, domain). Again, because no one should be trying to send e-mails to your Snort server, it shouldn't matter that your server's name isn't in your ISP's DNS.
Accept the default 127.0.0.1 address for an incoming SMTP connection.
On the "other destinations" screen, backspace everything out of the field (so it's blank) and tab to OK and hit Enter.
Because you used your ISP's domain name you can just accept the default value for the "visible domain" value.
In the "outgoing smarthost" field, backspace out whatever is there and enter the name or IP address of your ISP's SMTP server (the same SMTP server you have entered in your e-mail client program (Thunderbird, Outlooks, etc.).
Accept the default 'No' to keeping DNS queries minimal and hit Enter.
Accept the default 'No' to splitting the configuration files and hit Enter.
Exim will then restart automatically with your new configuration.
Since day one you needed to use an ID (your e-mail ID) and password to access your received (POP) e-mail messages. These days more and more ISPs are starting to require those same credentials to send (SMTP) e-mail messages. If your ISP requires SMTP authentication you'll need to edit an Exim file to supply those credentials. Enter the command:
nano /etc/exim4/passwd.client
and enter an asterisk, your e-mail login ID, and your e-mail password, separated by colons, like so:
*:billgates:loveslinux
Exit the editor saving the changes. Snort can now use Exim as an e-mail client to send the daily summaries. Don't be surprised if you don't get any e-mails. Snort will only send them when it's detected suspicious traffic. If you don't see any stats on the graphs on the BASE home page, you won't get any e-mails.
Managing Rules By design, the /etc/snort/snort.conf configuration file holds all the rules Snort will use for traffic comparisons. While this is logically the case, it is not physically true.
If you open the /etc/snort/snort.conf file in a text editor and page down to section 6 and read the comments. Below the comments you'll see a bunch of include statements where various rule files (located in the /etc/snort/rules directory) are included into the configuration file. The actual rules themselves are not entered directly into the configuration file to simplify management. Note that the include statements that have a pound symbol (#) in front of them are the disabled rules. (Note that you can disable rules by disabling an entire rule file inthe /etc/snort/snort.conf file, or by disabling individual rules within a rule file as you will see below.)
Any rule files that start out with the word community are rules written by Snort users. They do go through a couple checks by the Snort team to make sure they won't break your Snort installation, but they don't get the same scrutiny as those rules written by the Snort team. As you'll see in the configuration file, quite a few of these community rule files are enabled by default. If you're getting a lot of false alerts related to a specific application, you may want to try disabling the community rule file in Snort's configuration file as a first step and then try and narrow it down.
If you want to play around with editing or customizing rules, always make a backup copy of the original rule file before you start making any changes. This will make it easy to restore the default operation should an errant rule change hose things up.
If you want to create your own rules from scratch, add them to the local.rules file. This file is empty but included by default. Make sure to give your own rules a SID (see below) of 1000000 (one million) or higher.
The rule files are text files so you can open them up in any text editor. For example, open one of the rule files with the command:
nano /etc/snort/rules/web-iis.rules
If you page down you'll see that the individual rules all start with the alert keyword. Quite a few rules have a pound (#) character in front of alert to comment them out to disable them. (You can comment out individual rules in a rule file or you can comment out an entire rule file in Snort's configuration file.)If you cursor down to a rule and arrow to the right eventually you'll see the SID keyword. Each individual rule has it's own unique SID. As you'll see below, if you ever modify a rule, you'll want to make note of its SID.
Where to learn more - The best of our bookshelves:
More info...Snort IDS and IPS Toolkit covers Snort's operation in depth. You will understand what all the statements in the snort.conf and rule files do and how to modify them to optimize Snort for your environment. They even cover writing your own rules, preprocessors, and plugins. This focus on the "trees" does not exclude a look at the "forest" however. The book starts out discussing IDSs in general, their benefits and limitations, and how they fit into a larger security framework. It also covers 3rd party Snort utilities like Oinkmaster. Updating Rules
Just like updating your virus signatures, you'll want to make sure your Snort signatures are up-to-date. Snort's rule updates are called VRT rules (written by Snort's Vulnerability Research Team). In order to download the updates you need to register at www.snort.org to get your free oinkcode. (When you register you get a Web site login and once you log in there's a "Get Code" button near the bottom of your account page.) This code allows you to download rules after a 30-day hold period. You can also choose the higher-level, pay-for subscription service option if you want to be able to get the rules without the 30-day waiting period.
Luckily, Andreas Ostling helps us out with pulling down rule updates. Andreas wrote Oinkmaster which is a Perl script offering a lot of options. Oinkmaster got installed automatically when we installed Snort so all we need to do is update the configuration file and set up a cron job to run it.
Open the Oinkmaster configuration file with the command:
nano /etc/oinkmaster.conf
This configuration file is a little out of date, referring only up to Snort 2.2 being the current version. Snort has also changed their download path. Comment out the url line for 2.2 by putting a pound (#) character in front of it and add the following line beneath it:
url = http://www.snort.org/pub-bin/oinkmaster.cgi/oinkcode/snortrules-snapshot-2.7.tar.gz
If you look further down in the file you'll see skipfile statements, one of which is for the local.rules file (which is why this is where you want to put your own rules). Any rule or configuration file specified in a skipfile statement will not be touched by Oinkmaster.Even further down in the file you'll see sections for modifysid and disablesid statements which is what you'll need to use to preserve any rule changes through updates. It may be easier just to disable the rule in the rules file, copy it over to local.rules and make your changes there. DON'T FORGET TO CHANGE THE SID!
Exit the editor saving the file and we'll take it out for a spin. Oinkmaster does require that you specify an output directory (where your current rules are located). We can check Oinkmaster's configuration without actually updating our current rule files using the -c option so enter the command:
oinkmaster -o /etc/snort/rules -c
It will download the rules (it may take awhile) and then unpack and process them. A lot of stuff will scroll on your screen but at the end will be a list of new rule files. If you want to use these new rules (once we actually add them) you'll need to add include statements for them in the snort.conf file (not the oinkmaster.conf file). Add the include statements for them and then just comment them out if they seem to generate too many false positives.This addition of new files is one reason you may not want to automate the updating of the rules using a cron job. You won't see that new rule files were added. If you do add new include statements you'll need to restart Snort so it re-reads the configuration file. (There is no need to restart Snort if you simply update the rules.)
Now lets try updating the rules for real using the above command without the -c option.
oinkmaster -o /etc/snort/rules
If you update the /etc/snort/snort.conf file, restart Snort with the command:
/etc/init.d/snort restart
Getting Snort installed and updated is a good start but you'll need to watch for false positives and make any rule changes necessary to minimize them. This is the process of "tuning" Snort for your environment. While there are a ton of rules contained in all those rule files, finding a rule is not all that hard. For example, a rule that's a common cause of false positives is the "L3retriever ping" rule. (Layer 3 Networks offers a utility called Retriever.) We can find which rule file(s) contain this rule with the command:
grep retriever /etc/snort/rules/*
The command output shows that the text string "retriever" is in two rule files, "L3retriever ping" is in the icmp.rules file and "L3retriever HTTP Probe" is in the web-misc.rules file. We open the icmp.rules file with the command:
nano /etc/snort/rules/icmp.rules
and we can see that the "L3retriever ping" rule is the second one listed. We can disable this rule simply by placing a pound sign character (#) in front of it (and then restarting Snort).Naturally, you'll want to make sure that the alerts truly are false positives before you disable the rule.
So you finally get your Snort box up and running and tuned to your environment and now you want to start fresh. How do you clear out all the old alerts? Simple. Just click on the Cache & Status link near the bottom of the BASE home page and then click on the Clear Data Tables button.
There is a man page for Snort but there is much more documentation available on the Snort Web site. If you're going to seriously use Snort I'd recommend getting one of several books available on it.







