LINUX.ORG.RU

Сообщения bodigard

 

Perl AnyEvent-HTTP идентифицировать callback

Доброго времени суток уважаемое сообщество !

возникла необходимость проверять на доступность несколько тысяч url, решил использовать для этого AnyEvent::HTTP как наиболее быстрый, на мой взгляд

делаю стандартно в цикле запрос http_head (по 100 за раз)

my $cv = AnyEvent->condvar();

my $guard;
$guard = http_head($url, timeout => 1, sub {
    undef $guard;
    my $header = $_[1];
    if($header->{'Status'} =~ /^2/){
		print "Status: OK\n";
    }
    else{
        $log->info("Status: Error,  $header->{'Reason'}");
    }
	if($max_request == $y){
		$cv->send("done");
	}
});

my $result = $cv->recv();

это всё дело как-бы работает, и довольно шустро но проблема в чём, не могу из callback определить к какой url он принадлежит, ведь url http_head($url ... и $header->{'URL'} это вовсе не всегда 1но и то-же а при возникновении ошибки (перенаправление, недостпность что-то ещё) мне нужно потом сообщить что такой-то url с таким-то id недоступен

пробовал ввести id для url (точнее они и так есть в БД где хранятся url) но тоже не получилось, ибо callback-и выполняются в произвольном порядке

подскажите если не трудно есть ли какой-то способ из callback выяснить какой http_head($url ... его вызвал ?

 , ,

bodigard
()

пользовательские данные,sk_buff

Доброго времени суток, помогите плиз разовбраться как правильно получить доступ к данным пользователя в sk_buff. есть модуль фильтрации http трафика и работал он прекрасно, но понадобилось перенести на другой сервер, в результате код работающий на 1ном железе перестал работать на другом :(

Так как прошлый сервер благополучно переустановили то сравнивать можно лишь с виртуалкой, версии ОС и библиотек идентичны на виртуалке и на железном сервере.

на виртуалке получаю данные пользовалетя так

user_data_ptr = (char *)(skb->data + sizeof(struct iphdr) + sizeof(struct tcphdr));
работает прекрасно, см результат 2

если тоже самое сделать на железном сервере то получу результат 1

далее, на железном сервере вставляю мощьный костыль в виде копирования sk_buff посредством skb_copy и получаю правельный результат, результат 2. но от этого костыля очень хочеться уйти ...

есть подозрение что на железном сервере каким-то образом в памяти фрагментируется sk_buff, но как правильно к этому подойти ума не приложу :(

вот кусок кода (за стиль извиняюсь, переписывал его раз на 20ть по разному, но работает только этот, с копированием) блин, ещё и разметку форум бъёт :( может подскажете как правильно вставлять куски кода ?

unsigned int main_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
                int (*okfn)(struct sk_buff*))
{
        int i,get_len;
        struct iphdr *ip;// = (struct iphdr *)skb->data;
        struct tcphdr *tcp;// = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
        char *p, *user_data_ptr;
        struct sk_buff *cpy = NULL;

        //cpy = kmalloc(skb->truesize,GFP_ATOMIC);
        //if(cpy != NULL) cpy = skb_copy(skb,GFP_ATOMIC);
        //else return NF_ACCEPT;

		//делаем копию skb
        cpy = skb_copy(skb,GFP_ATOMIC);
        if(cpy == NULL){
             printk("error SKB_COPY\n");
             return NF_ACCEPT;
        }

        ip = (struct iphdr *)cpy->data;
        tcp = (struct tcphdr *)(cpy->data + sizeof(struct iphdr));

        if(ip->version == 4 && ip->protocol == IPPROTO_TCP ){
/*
                printk("pro=TCP, src=%d.%d.%d.%d:%d\t", ntohl(ip->saddr)>>24, (ntohl(ip->saddr)>>16)&0x00FF,
                                                            (ntohl(ip->saddr)>>8)&0x0000FF, (ntohl(ip->saddr))&0x000000FF,ntohs(tcp->source));
                printk("dst=%d.%d.%d.%d:%d\n", ntohl(ip->daddr)>>24, (ntohl(ip->daddr)>>16)&0x00FF,
                                                            (ntohl(ip->daddr)>>8)&0x0000FF, (ntohl(ip->daddr))&0x000000FF,ntohs(tcp->dest));
*/
                if(tcp->dest == htons(80)){
						
						//получаем указатель на данные пользователя из копии
                        user_data_ptr = (char *)(cpy->data + sizeof(struct iphdr) + sizeof(struct tcphdr));
						
						//получаем указатель на данные пользователя из оригинала
						//user_data_ptr = (char *)(skb->data + sizeof(struct iphdr) + sizeof(struct tcphdr));
				
						//DEBUG инофрмация о размерах
                        get_len = cpy->tail - cpy->data;
                        if(get_len > 40){
                            printk("len - %i\n",get_len);
                            printk("len1 - %i\n",strlen(user_data_ptr));
                            printk("skb->len - %i\n",cpy->len);
                            printk("skb->data_len - %i\n",cpy->data_len);
                        }
                       
                        get_len = strlen(user_data_ptr); //skb->data_len;

                        if(get_len > 100){ //handshake и разный мусор нам не интересен
                            printk("\nSTART ORIGIN_DATA\n");
                            for(i=0;i<get_len;i++){
                                //printk("%x", user_data_ptr[i]);
                                printk("%c",user_data_ptr[i]);
                            }
                            printk("\nEND ORIGIN_DATA\n");
							kfree_skb(cpy);
                            return NF_ACCEPT;
						}
				}
		}
	kfree_skb(cpy);
	return NF_ACCEPT;
}

так регестрирую функцию

//netfilter out
        nf_outgoing.hook = main_hook;
        nf_outgoing.pf = PF_INET;
        nf_outgoing.hooknum = NF_INET_PRE_ROUTING;//NF_INET_PRE_ROUTING;//NF_INET_FORWARD;//NF_INET_POST_ROUTING;//NF_INET_LOCAL_IN;4;//NF_INET_LOCAL_OUT;
        nf_outgoing.priority = NF_IP_PRI_FIRST;
        nf_register_hook(&nf_outgoing);

Результат 1

Sep 10 15:53:26 proxy kernel: len - 40
Sep 10 15:53:26 proxy kernel: len1 - 14
Sep 10 15:53:26 proxy kernel: skb->len - 429
Sep 10 15:53:26 proxy kernel: skb->data_len - 389
Sep 10 15:53:26 proxy kernel:
Sep 10 15:53:26 proxy kernel: START ORIGIN_DATA
Sep 10 15:53:26 proxy kernel: 5efffffff5yfffffffb2cfffffff51111ffffffa5Bfffffff6ffffff8e201005efffffff5yfffffffb8ffffffca13e26ffffffbfqfffffff414000044000010pffffffceffffff8613ffffffc1ffffffc8ffffffc7ffffff99fff
fffe8c1c60223effffffcc75fffffff9bffffff87ffffff88KDfffffff015ffffffc535ffffffdbffffffc0fffffff0ffffffacffffff8bffffffe7c113833fRffffffb829ffffff8920ffffff97o7f26ffffffb9fffffff7W5bffffffb5Effffffbdffffffb3ffffff
b7ffffff9e17ffffff8dffffffefk1d2effffffa811ffffff91f3ffffffc7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Sep 10 15:53:26 proxy kernel: END ORIGIN_DATA   

Результат 2

Sep 10 16:45:27 proxy kernel: len - 532
Sep 10 16:45:27 proxy kernel: len1 - 492
Sep 10 16:45:27 proxy kernel: skb->len - 532
Sep 10 16:45:27 proxy kernel: skb->data_len - 0
Sep 10 16:45:27 proxy kernel:
Sep 10 16:45:27 proxy kernel: START ORIGIN_DATA
Sep 10 16:45:27 proxy kernel: GET /su/ HTTP/1.1
Sep 10 16:45:27 proxy kernel: Accept: text/html, application/xhtml+xml, */*
Sep 10 16:45:27 proxy kernel: Referer: http://ya.ru/
Sep 10 16:45:27 proxy kernel: Accept-Language: ru-RU
Sep 10 16:45:27 proxy kernel: User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Sep 10 16:45:27 proxy kernel: Accept-Encoding: gzip, deflate
Sep 10 16:45:27 proxy kernel: Host: kiks.yandex.ru
Sep 10 16:45:27 proxy kernel: Connection: Keep-Alive
Sep 10 16:45:27 proxy kernel: Cookie: ys=gsync.1378790047; yandexuid=1471721651378795249; fuid01=522ebef255999fb9.qOOODita1WHGvfdQjHhsPF4h2eDNI62T1gxRp8ZM5taWSHeLQaQheLKMsmAYJPj7JxTvF32pF5rBgfz4xrFGSpnIU00oyRBG9
nX16VOtoS2h_X1-snwHoCTc4gTuOB2N
Sep 10 16:45:27 proxy kernel: END ORIGIN_DATA

Заранее благодарен !

С уважением.

bodigard
()

libnet, не уходят пакеты

подскажите, почему не уходят пакеты

int  packet_size;
    libnet_t *lnet;
    char errbuf[LIBNET_ERRBUF_SIZE];
    libnet_ptag_t ip = 0, tcp = 0;
    
    lnet = libnet_init(LIBNET_RAW4, "eth0", errbuf);
    if (lnet == NULL){
        fprintf (stderr, "Error opening context: %s", errbuf);
        return -1;
    }
    packet_size = LIBNET_IPV4_H + LIBNET_TCP_H;
//выводит читабельные IP 
    printf("saddr = %s\ndaddr = %s\n",libnet_addr2name4(data->saddr,LIBNET_DONT_RESOLVE),libnet_addr2name4(data->daddr,LIBNET_DONT_RESOLVE));
    tcp = libnet_build_tcp(data->dport,         //src port
        data->sport,           //dst port
        0,                            //seq
        0,                            //ack
        TH_SYN,                  //flag
        65534,                    //window
        0,                            //csum
        0,                            //urg
        LIBNET_TCP_H,       //header len
        NULL,                       //payload
        0,                             //payload len
        lnet,                         //libnet context
        tcp);                         //ptag
    if(tcp == -1){
        fprintf(stderr, "Error building TCP header: %s\n", libnet_geterror(lnet));
        return -1;
    }
    ip = libnet_build_ipv4(packet_size,         //size
        0,                        //tos
        id,                       //id IP packet
        0,                        //do not fragment
        IPPROTO_TCP,    //protocol
        64,                      //ttl
        0,                        //csum
        data->daddr,      //src addr
        data->saddr,      //dst addr
        NULL,                  //payload
        0,                        //payload len
        lnet,                    //libnet context
        ip);                      //ptag
    if(ip == -1){
        fprintf(stderr, "Error building IP header: %s\n", libnet_geterror(lnet));
        return -1;
    }
    if ((libnet_write (lnet)) == -1){
        fprintf (stderr, "Unable to send packet: %s\n", libnet_geterror (lnet));
        return -1;
    }

ошибок никаких не выдаёт, а tcpdump пакеты не видит

libnet-1.1.2.1-2.2.el6.rf.i686

centos 6.4

заранее благодарен !

bodigard
()

Не уходят пакеты с установленным ACK, PSH+ACK

Доброго времени суток всем !

есть модуль ядра написанный на Си который ловит пакеты на 80 порт, анализирует GET запрос (т.е. пропускает 3 пакета handshakе т.к. они не несут нагрузки и неизвестно к какой страничке/сайту в конечном итоге пойдёт запрос) и принимает решение дропнуть или пропустить пакет.

задача: хотелось-бы чтоб пакет не просто дропался модулем(на стороне пользователя это выглядит будто сайт просто лёг) а возвращалась страничка с описанием почему доступ закрыт.

сейчас пробую сделать это дело след образом

1 - модуль ядра, при запрещённом GET, шлёт через netlink в userspase следующую структуру

struct helper_data{
    __u32 saddr;
    __u32 daddr;
    __u16 sport;
    __u16 dport;
    __u32 SEQb;
    __u32 ACKb;
};

2 - в userspase демон эту структуру ловит и по идее(судя по анализу с wireshark) должен отправить 2 пакета, ACK (seq=ACKb, ack_seq=345) и ACK(seq=ACKb, ack_seq=345)+PSH+нагрузка(HTTP ответ), соответственно выставив адреса, порты, посчитав контрольную сумму TCP.

но пакеты с выставленный ACK и ACK+PSH не отправляются (tcpdump на сервере и wireshark на клиенте не видят их), при этом sendto ошибок не возвращает.

далее попробовал проанализировать, отправляются пакеты PSH, FIN+ACK, SIN+ACK, RST, и остальные вменяемые и невменяемые связки

при этом если saddr поставить левый и выставить seq из присланной модулем структуры и новый ack_seq, то пакеты отправляются и принимаются, но при этом tcpdump говорит что seq и ack_seq установлены в 1 а не в те значения что я выставил

window в пакете ставлю заведомо больше значений seq и ack_seq

вопщем прошу помощи в понимании как правильно послать поддельный пакет с ответом http, или возможно другой алгоритм решение поставленной задачи.

заранее благодарен за помощь !

да, чуть не забыл, сервер CentOS 6.4 клиент WinXp SP3 оба в VirtualBox

bodigard
()

RSS подписка на новые темы