Показаны сообщения с ярлыком lighttpd. Показать все сообщения
Показаны сообщения с ярлыком lighttpd. Показать все сообщения

четверг, 4 февраля 2010 г.

mason + lighttpd fastcgi

включаем mason в lighttpd

сначало готовим скрипт mason.cgi


#!/usr/bin/perl
use CGI::Fast;
use HTML::Mason::CGIHandler;
use URI;

{
package HTML::Mason::Commands;

## anything you want available to components
use Storable qw(freeze thaw);
use HTTP::BrowserDetect;

## An example of how to keep a $dbh persistent
##our $dbh = DBI->connect_cached(
## 'dbi:Pg:dbname=dbname'
## , 'username'
## , 'password'
## , {AutoCommit=>0, RaiseError=>1, PrintError=>1}
##) || die "Could not Connect to DB".$dbi::errstr ;

}

# lazily-instantiated variables
my $cgi;
my $h;

while ($cgi = new CGI::Fast())
{
## make sure it is alive! (if not it will reconnect)
## $HTML::Mason::Commands::dbh->ping;

my $uri = URI->new( $ENV{REQUEST_URI} );

## this is a hack, that emulates mod_perl behavior see notes at bottom
## You might not want this hack, and it might be worse than not having it
$uri->path( $uri->path . 'index.html' )
if $uri->path =~ /\/$/
;

$ENV{PATH_INFO} = $uri->path;
$ENV{QUERY_STRING} = $uri->query;
$ENV{REQUEST_URI} = "$uri";

# this is lazily instantiated because %ENV is not set at startup time
if (! $h) {
$h = HTML::Mason::CGIHandler->new(
comp_root => $ENV{MASON_COMP_ROOT}
, data_dir => $ENV{MASON_DATA_ROOT}
, error_mode => 'fatal'
, error_format => 'line'
## Three good globals dbh user and session
, allow_globals => [qw/$dbh $U $S/]
);
}

## hand off to mason
eval { $h->handle_cgi_object($cgi) };

## catch error
if ( my $raw_error = $@ ) {
warn $raw_error;
# print out a pretty system error page and log $raw_error
}
## things went well
else {
$HTML::Mason::Commands::dbh->commit;
}

}

exit 0;


добавляем в lighttpf.conf

fastcgi.map-extensions = ( ".css" => ".html", "/" => ".html" )
        index-file.names = ( "index.html" )
        url.access-deny = ( ".mhtml" ) ## add autohandler/dhandler if you'd like
        fastcgi.server = ( ".html" =>
        ((
                "socket" => "/tmp/fastcgi.socket",
                "bin-path" => "/etc/lighttpd/bin/mason.cgi",   # пусть до скрипта
                "check-local" => "disable",
                "bin-environment" => (
                "MASON_COMP_ROOT" => "/www/myproject",
                "MASON_DATA_ROOT" => "/www/myproject/data",
                ),
        ))
        )


index.html кладем в comp_root
простенький helloworld
<HTML>
   <HEAD>
   <TITLE> Hello <% $worldname %> world!!</TITLE>
   </HEAD>
   <BODY bgcolor="#FFFFFF">
   Hello World<BR>
   This is my <B><% $count %></B> Mason component.
   </BODY>
</HTML>
<%init>
   my $worldname = "Great";
   my $count = "first";
</%init>
<%args>
</%args>

вторник, 29 сентября 2009 г.

lighttpd reverse proxy

только для lighttpd >1.5


proxy-core.protocol = "http"
#proxy-core.balancer = "carp"
proxy-core.balancer = "round-robin"

proxy-core.rewrite-response = ("Location" => ( "^http://my.example.com/(.*)" => "http://remote.site.com/" ) )
proxy-core.rewrite-request = ( ("^/(.*)$" => "http://my.example.com") )
proxy-core.backends = ( "remote.site.com" ) # вот тут нельзя писать протокол, а то будет ошибка.

четверг, 3 сентября 2009 г.

antiddos: varnish+lighttpd

Сперто с http://habrahabr.ru

Простой способ защиты от HTTP DDoS — включить syn-cookies и заблокировать подонков. Но что делать если атакует 5к-10к хостов да еще и с динамическими IP? Тут нам на помощь придет frontend-backend архитектура c промежуточным кэшированием! Почему с промежуточным кэшированием? А потому что в моем случае от шквала запросов от frontend'а backend умирал унося за собой систему.

Итак алгоритм действий:

* Меняем порт нашего backend сервера на любой отличный от 80 (пусть будет 2080)
* Устанавливаем Varnish
* Устанавливаем и настраиваем lighttpd
* Ограничиваем кол-во соединений с одного хоста средствами iptables


Так, как, у меня в наличии было несколько серверов, то будет рассмотрена версия конфигурации именно с несколькими серверами, но никто не мешает вам все это запихнуть на один сервер =)

Как менять порт вашего любимого веб-сервера я думаю рассказывать не нужно, предлагаю перейти сразу к настройке Varnish.

Собственно устанавливаем сам пакет:
apt-get update && apt-get install varnish

Далее приводим C-подобный файл конфигурации (в Ubuntu это /etc/varnish/default.vcl) приблизительно к такому виду:
backend default {
.host = "1.1.1.1"; #IP нашего backend'а
.port = "2080"; #порт
.first_byte_timeout = 300s; #без этого таймаута varnish не хотел забирать контент с backend'а
}

acl purge {
"localhost"; #разрешаем очистку кэша только с локалхоста
}

sub vcl_recv {
if (req.request == "GET" && req.url ~ "\.(jpg|jpeg|gif|ico)$") {
lookup;
}

if (req.request == "GET" && req.url ~ "\.(css|js)$") {
lookup;
}

if (req.request == "GET" && req.url ~ "\.(pdf|xls|vsd|doc|ppt|iso)$") {
lookup;
}

if (req.request == "POST") {
pipe;
}

if (req.request != "GET" && req.request != "HEAD") {

if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
lookup;
}

pipe;
}

if (req.http.Expect) {
pipe;
}

if (req.http.If-None-Match) {
pass;
}

if (req.http.Authenticate || req.http.Authorization) {
pass;
}
lookup;

}

sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}

sub vcl_miss {
if (req.http.If-Modified-Since) {
pass;
}

if (req.request == "PURGE") {
error 404 "Not in cache.";
}
}

sub vcl_fetch {
if ( obj.http.x-accel-redirect ~ ".*" ) {
set req.url = obj.http.x-accel-redirect;
restart;
}
}


Перезапускаем varnish: service varnish restart

Теперь можно приступить к установке и настройке нашего frontend'а — lighttpd.
Я предпочитаю брать lighttpd отсюда, но вам никто не мешает скачать его из репозиториев дистрибутива (apt-get install lighttpd).
И правим конфиг до тех пор, пока он не примет следующий вид:
server.modules = (
"mod_cache",
"mod_proxy",
"mod_access",
"mod_evasive"
)

server.network-backend = "writev"
server.max-keep-alive-requests = 4
server.max-keep-alive-idle = 4
server.max-read-idle = 10
server.max-write-idle = 30
server.event-handler = "linux-sysepoll"
server.stat-cache-engine = "disable"
server.protocol-http11 = "enable"
server.max-worker = 2 #Если у вас один процессор или вы все запускаете на одном сервере то стоит поставить 1
server.max-fds = 10000
server.max-connections = 5000
server.port = 80
server.document-root = "/var/www"
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "www-data"
server.groupname = "www-data"
etag.use-inode = "enable"
etag.use-mtime = "enable"
etag.use-size = "enable"
server.dir-listing = "disable"
evasive.max-conns-per-ip = 3 #Разрешаем только три одновременных подключения

cache.enable = "enable" #Включаем кэширование на стороне лайти
cache.bases = ("/var/spool/cache") #Здесь мы будим хранить кэш
cache.max-memory-size = 40960 #40Gb
cache.lru-remove-count = 512
cache.support-queries = "enable"
cache.dynamic-mode = "enable"
cache.refresh-pattern = (
"\.(?i)(js|css|xml|po)$" => "240", # update js/css/xml every 4 hours and on refresh requests
"\.(?i)(htm|html|shtml)$" => "30 use-memory", # update html/htm/shtml every 30 minutes and on refresh requests
"\.(?i)(jpg|bmp|jpeg|gif|png)$" => "2880", # update graphics files every 2 days
"\.(?i)(rar|zip|wmv|iso|avi|mp3|ape|rm|mpeg|mpg|wma|asf|rmvb|flv|mkv|ogg|ogm|swf|flac)$" => "0 fetchall-for-range-request", # cache media file forever
".(?i)php$" => "5", # update php request every 5 minutes
"." => "30 use-memory" #
)

mimetype.use-xattr = "enable"
include_shell "/usr/share/lighttpd/create-mime.assign.pl"

#Bad users go to hell
$HTTP["useragent"] == "" {
url.access-deny = ( "" )
}

$HTTP["host"] =~ "(^|\.)habrahabr\.ru$" {
proxy.balance = "round-robin"
proxy.server = ( "/" =>
(
( "host" => "1.2.1.1", "port" => 6081 ), #Отправляем запросы
( "host" => "1.2.1.2", "port" => 6081 ), #серверам varnish
( "host" => "1.2.1.3", "port" => 6081 ),
( "host" => "1.2.1.4", "port" => 6081 )
)
)
}
proxy.worked-with-mod-cache = "enable"


И напоследок iptables и небольшой тюнинг системы:

Разрешаем 10 подключений в секунду с одного IP:
iptables -I INPUT 1 -p tcp -m hashlimit --hashlimit-upto 10/sec --hashlimit-burst 10 --hashlimit-mode srcip --hashlimit-name HTTPD_DOS -m tcp --dport 80 -m state --state NEW -j ACCEPT
Увеличиваем количество открытых файлов:
ulimit -n 5000
Плюшки для sysctl.conf:
vm.swappiness=10
vm.vfs_cache_pressure=10000
vm.dirty_ratio = 1
vm.dirty_background_ratio = 1
vm.dirty_writeback_centisecs = 250
vm.dirty_expire_centisecs = 3000
kernel.panic = 10
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_sack = 1
net.core.rmem_max = 16777216
net.core.rmem_default = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.netfilter.ip_conntrack_max = 1048576
net.nf_conntrack_max = 1048576
net.ipv4.icmp_echo_ignore_all = 1
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 15
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 15
net.ipv4.ip_local_port_range= 10000 65000

Как все это работает? lighttpd получает запрос от клиента и если он удовлетворяет определенным критериям (в нашем случае это не пустой User-agent, клиент запрашивает домен habrahabr.ru и это не 4ый одновременный запрос) отправляет запрос одному из серверов varnish. Varnish проверяет свой кэш на наличие нужного пользователю контента отдает его либо из кэша либо отправляет запрос на backend, если в кэше данного контента нет или он устарел.

пятница, 24 июля 2009 г.

lighttpd fastcgi catalyst

fastcgi.server = (
"" => (
"germion" => (
"socket" => "/tmp/germion.socket",
"check-local" => "disable",
"bin-path" => "/germion/script/germion_fastcgi.pl",
"min-procs" => 2,
"max-procs" => 5,
"idle-timeout" => 20,
)
)
)

понедельник, 1 июня 2009 г.

lighttpd digest auth

lighttpd.conf

раскомментарить mod_auth

добавить в секцию host или URL

auth.backend = "htdigest"
auth.backend.htdigest.userfile = "/etc/lighttpd/.passwd"
auth.debug = 2


auth.require = ( "/" =>
(
"method" => "digest",
"realm" => "Restricted Area",
"require" => "valid-user"
))

затем в консоли

htdigest -c /etc/lighttpd/.passwd "Restricted Area" login
chown www:www /etc/lighttpd/.passwd
chmod 400 /etc/lighttpd/.passwd

четверг, 4 декабря 2008 г.

fastcgi php wrapper

wrapper для lighttpd

#!/bin/sh
PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS

#export PHP_FCGI_MAX_REQUESTS=0
exec /usr/local/bin/php-cgi