from socket import socket, AF_PACKET, SOCK_RAW
ETH_P_ALL = 0x0003
print(«Starting»)
interface = «enx7cc2c65485c0»
# interface_mac = 7c:c2:c6:54:85:c0
# Note: When sending ethernet frames, only the following data is actually supplied at this level:
# — Destination MAC
# — Source MAC
# — EtherType
# — Payload data
arp_packet = bytearray([
# Ethernet frame data exposed at this level (missing Preamble / Start of frame delimiter from hardware level)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # Destination MAC (broadcast)
0x7c, 0xc2, 0xc6, 0x54, 0x85, 0xc0, # Source MAC
0x08, 0x06, # EtherType (0x0806 for ARP)
# ARP packet data starts here
0x00, 0x01, # Hardware type (Ethernet)
0x08, 0x00, # Protocol type (IPv4)
0x06, # Hardware size
0x04, # Protocol size
0x00, 0x01, # Opcode (request)
0x7c, 0xc2, 0xc6, 0x54, 0x85, 0xc0, # Sender MAC address
0xC0, 0xA8, 0x01, 0x02, # Sender IP address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Target MAC address (unknown)
0xC0, 0xA8, 0x01, 0x01, # Target IP address
# No padding or frame check sequence CRC is added here either
])
ethernet_frame = bytearray([
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # Destination MAC (broadcast)
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, # Source MAC
0x12, 0x34, # Custom EtherType (0x1234)
# Payload (just some test data)
0xde, 0xad, 0xbe, 0xef # Example payload
])
# AF_PACKET is a low-level interface to network devices
# SOCK_RAW, when combined with AF_PACKET, refers to raw ethernet packets
with socket(AF_PACKET, SOCK_RAW) as raw_socket:
print(raw_socket)
print(f»Binding to interface: {interface}«)
raw_socket.bind((interface, ETH_P_ALL))
print(«Sending raw ARP packet»)
bytes_sent = raw_socket.send(arp_packet)
# bytes_sent = raw_socket.send(ethernet_frame)
print(f»Sent {bytes_sent} bytes to the interface»)
Сразу скажу: то, чем мы с вами будем здесь заниматься, не претендует, скажем, на какую-то промышленную применимость. Более того, я признаю, что мой код в данном примере может быть ужасен, страшен и ненужен. И тем не менее — почему бы не поперехватывать пакеты посреди недели? Так, слегка.
Итак, сегодня мы вот что наколдуем:
1. Реализуем простейший пассивный перехватчик пакетов для TCP и UDP
2. Засунем его в C-библиотеку в виде расширения для Python
3. Приделаем ко всему этому интерфейс итератора, дабы байты сыпались, как из рога изобилия
4.…
5. PROFIT!
Зачем все это нужно?
Зачем нужны снифферы? Чтобы нюхать сетевой трафик. Нет, я не шучу, с английского глагол «to sniff» так и переводится — «нюхать». Ладно-ладно, будем более научны — с их помощью можно и нужно анализировать сетевые пакеты, проходящие через сетевую карту компьютера.
Снифферы бывают пассивные и активные. Пассивный сниффер делает именно и только то, что от него требуется — перехватывает для анализа трафик, проходящий сквозь сетевую карту компьютера, на котором он установлен. Казалось бы, куда уж круче? Однако же, активный сниффер не только мониторит сетевую карту, но и всячески пытается добраться до трафика, который гуляет по локальной сети и не предназначен для чужих глаз. Делает он это, например, с использованием ARP-Spoofing и всяких прочих грязных трюков. Кстати, в некоммутируемых сетях (основанных на репитерах и хабах) пассивный сниффер может внезапно обнаружить в себе суперсилы, ибо при отсутствии коммутации все пакеты в таких сетях рассылаются по всем хостам. Принимать их, конечно, должны только адресаты, но…
А вот чтобы их принимать — надо перво-наперво заставить сетевую карту уволить ее личного секретаря, который фильтрует корреспонденцию, и начать читать все и сразу. Научно это называется «Promiscuous mode», то есть «Неразборчивый режим». И тут есть засада:
Да, для перевода карты в неразборчивый режим требуются права root. Поэтому и наш скрипт попросит их для запуска. Такие дела.
Ну и чо?
Как говорил один известный киношный персонаж, «We need to go deeper». То есть, нырнуть поглубже в уровни OSI, на канальный уровень. Для этого при создании сокета необходимо указать константу PF_PACKET вместо PF_INET:
int s_sock;
struct ifreq ifr;
strcpy(ifr.ifr_name, IFACE);
if ( (s_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
perror("Error creating socket");
exit(-1);
}
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(s_sock, SIOCGIFFLAGS, &ifr) < 0) {
perror("Unable to set promiscious mode for device");
close(s_sock);
exit(-1);
}
Обычно при открытии подобного сокета указывается конкретный протокол, по которому идет перехват. Если же указать константу ETH_P_ALL — будут перехватываться все. Структура ifreq используется в Linux для руления сетевым интерфейсом на низком уровне через ioctl(), а IFACE в данном случае — просто строка с именем смотрящего в сеть интерфейса, например, «eth0».
Собственно, теперь все, что нам остается — читать данные из сокета в цикле и смотреть, что из этого получится:
int n = 0;
char buf[MTU];
n = recvfrom(s_sock, buf, sizeof(buf), 0, 0, 0);
MTU здесь проще всего поставить равным 1500 — это определенный стандартом максимальный размер пакета в сетях Ethernet. Для сетей, построенных по другому стандарту, например, FDDI, значение может быть другим.
Поскольку мы работаем с Ethernet, данные о заголовках полученных пакетов проще всего записывать в специально предназначенную для этого структуру ядра — ethhdr. Для разных базовых протоколов вплоть до транспортного уровня существуют похожие структуры, которые, как ни сложно в это поверить, носят названия наподобие iphdr, tcphdr или даже udphdr (как говорится, «знаю отличную шутку про UDP, но не факт, что она до вас дойдет»). Как и полагается в старом добром C, это делается как-то так:
struct ethhdr eth;
memcpy((char *) ð, data, sizeof(struct ethhdr));
Мда… И как же засунуть это в Python?
Всем известно, что в питоне у нас все есть объект. В случае с генератором/итератором исключения так же не будет — мы должны создать объект, имеющий метод __iter__() и умеющий next(). У объекта есть куча полей, большинство из которых нам не нужны, поэтому осторожно — впереди куча нулей.
PyTypeObject PyPacketGenerator_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"packgen", /* tp_name */
sizeof(PacketGeneratorState), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)packgen_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)packgen_next, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
packgen_new, /* tp_new */
};
Из этого объявления видно, что рабочие методы нашего будущего объекта — это packgen_new(), packgen_next() и packgen_dealloc(). Последний является деструктором и в общем и целом без него можно обойтись, если очень хочется и нет лишних данных в памяти. Кроме того, нам потребуется структура, в которой мы будем хранить данные о состоянии объекта на текущей итерации. Поскольку единственное, что нам необходимо хранить — это сокет, его и объявим:
typedef struct {
PyObject_HEAD
int s_sock;
} PacketGeneratorState;
Как я сказал выше, нужно открыть сокет и настроить сетевую карту в режим шпиёнства. Проще всего это сделать прямо в методе инициализации объекта.
static PyObject *
packgen_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
int s_sock;
struct ifreq ifr;
strcpy(ifr.ifr_name, IFACE);
if ( (s_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
perror("Error creating socket");
exit(-1);
}
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(s_sock, SIOCGIFFLAGS, &ifr) < 0) {
perror("Unable to set promiscious mode for device");
close(s_sock);
exit(-1);
}
PacketGeneratorState *pkstate = (PacketGeneratorState *)type->tp_alloc(type, 0);
if (!pkstate)
return NULL;
pkstate->s_sock = s_sock;
return (PyObject *)pkstate;
}
В принципе, вполне реально было бы сделать возвращение пакетов из модуля в виде классов, но
мне было лень
я решил сделать проще и возвращать словарь (а если кто переделает по-своему — будет молодец). Все, что остается сделать — это определить, что у нас IP на сетевом уровне, а по IP-заголовку, в свою очередь, определить вышележащий протокол (если кто не помнит, протоколы обозначаются циферками и прописаны в /etc/protocols). Это все работает потому, что пакеты у нас похожи на творения поваров Burger King — каждый вышестоящий уровень дописывает свой заголовок к нижестоящему. Возьмем старых добрых братьев — TCP и UDP.
PyObject *packet;
packet = PyDict_New();
if (!packet)
return NULL;
if (ntohs(eth.h_proto) == ETH_P_IP) {
ip = (struct iphdr *)(data + sizeof(struct ethhdr));
PyDict_SetItemString(packet, "ip_source", PyString_FromFormat("%s", inet_ntoa(ip->saddr)));
...
if ((ip->protocol) == IPPROTO_TCP) {
tcp = (struct tcphdr *)(data + sizeof(struct ethhdr) + sizeof(struct iphdr));
PyDict_SetItemString(packet, "tcp_source_port", PyString_FromFormat("%d", ntohs(tcp->source)));
...
}
if ((ip->protocol) == IPPROTO_UDP) {
udp = (struct udphdr *)(data + sizeof(struct ethhdr) + sizeof(struct iphdr));
PyDict_SetItemString(packet, "udp_source_port", PyString_FromFormat("%d", ntohs(udp->source)));
...
}
}
return packet;
Вуаля!
Выглядит все в итоге примерно вот так:
Python 2.7.3 (default, Apr 20 2012, 22:44:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pysniff
>>> for i in pysniff.packgen():
... print i
...
{'ip_destination': '192.168.1.111', 'tcp_seq': '10972', 'ip_source': '173.194.32.53', 'tcp_offset': '8', 'tcp_source_port': '443', 'tcp_dest_port': '44021'}
{'ip_destination': '173.194.32.53', 'tcp_seq': '47475', 'ip_source': '192.168.1.111', 'tcp_offset': '8', 'tcp_source_port': '44021', 'tcp_dest_port': '443'}
{'ip_destination': '192.168.1.111', 'tcp_seq': '10972', 'ip_source': '173.194.32.53', 'tcp_offset': '8', 'tcp_source_port': '443', 'tcp_dest_port': '44021'}
{'ip_destination': '173.194.32.53', 'tcp_seq': '47475', 'ip_source': '192.168.1.111', 'tcp_offset': '8', 'tcp_source_port': '44021', 'tcp_dest_port': '443'}
Ради смеха создал репозиторий на github, вдруг захочется развить идею? Удачного вам сниффинга, не попадайтесь!
1. Original socket usage scenario
The network programming we usually use is to send and receive data at the application layer. Each program can only receive data sent to itself, that is, each program can only receive data from the bound port of the program. The received data usually includes only application-layer data, and the original header information is hidden in the transmission process. In some cases, we need to perform more low-level operations, such as listening to all data sent and received by the native machine, modifying headers, etc., whereas SOCK_STREAM and SOCK_DGRAMZ are usually used in the application layer and cannot meet this requirement.
With raw sockets, we can capture all IP packets sent to the local machine (including IP headers and TCP/UDP/ICMP headers) and all frames received by the local machine (including data link layer protocol headers). A common socket cannot process network packets such as ICMP and IGMP, but SOCK_RAW can. With raw sockets, we can construct our own IP headers.
2. Introduction to primitive socket classification and socket functions
There are two types of raw sockets: one handles data at the IP layer and above it by specifying the socket as the first parameter
AF_INET
To create this socket. The other is to process the data link layer and the data on it by specifying the socket as the first parameter
PF_PACKET
To create this socket.
Socket function:
int socket(int domain, int type, int proto)
#include <sys/types.h>
#include <sys/socket.h>
parameter
options
role
note
domain
AF_INET
Get data starting with the network layer (complete IP packets)
PF_PACKET
Get data from the start of the data link layer (link layer header +IP packet)
. .
Other domain options are not in use
type
SOCK_STREAM
Connection-oriented streaming sockets
SOCK_DGRAM
Connectionless packet socket
SOCK_RAW
The raw socket that receives the underlying data message
SOCK_PACKET
An outdated type is not recommended for the latest version
. .
Other type options are not used for the time being
proto
0
The default value is 0
ETH_P_IP
ETH_P_IP 0x800 Only IP data frames sent to the local MAC are received
ETH_P_ARP
ETH_P_ARP 0x806 Only arp data frames sent to the local MAC are accepted
ETH_P_RARP
ETH_P_RARP 0x8035 Only RARP frames sent to the local MAC are accepted
ETH_P_ALL
ETH_P_ALL 0x3 Receives all types of IP ARP Data frames sent to the local MAC address and all types of data frames sent from the local MAC address.(If promiscuous mode is enabled, non-local FRAMES are received.)
3. Socket usage and application scenarios
Creating a socket and its application scenario
Create a way
Work domain
Send a message
Receive a message
note
socket(AF_INET,SOCK_STREAM, 0)
The network layer
Receiving and sending are corresponding
port
Application layer data of
Received the packet destined for the local IP address
socket(AF_INET, SOCK_DGRAM, 0)
socket(AF_INET, SOCK_RAW, 0)
Only packets containing TCP or UDP headers or other transport protocols can be sent. IP headers and Ethernet frame headers are automatically sealed by the kernel
The user gets the complete IP packet containing the IP header
socket(PF_PACKET, SOCK_DGRAM, 0)
The link layer
Get IPV4 data link layer frames, excluding Ethernet frames (6 source MAC + 6 Destination MAC + 2)
Received the packet destined for the local MAC address. Procedure It is mainly used to obtain underlying data
socket(PF_PACKET, SOCK_RAW, 0)
Get an IPV4 data link layer frame, i.e. data containing Ethernet frame headers (14+20+(8: UDP or 20: TCP))
4. Comparison of two sockets
In the table above we know socket(AF_INET, SOCK_RAW…) Socket (PF_PACKET, SOCK_DGRAM,0) and **socket(PF_PACKET, SOCK_DGRAM,0)** can receive complete IP packets, but what is the difference between the received sockets? Next, a brief explanation:
Knot up is: socket (AF_INET SOCK_RAW, IPPROTO_TCP | IPPROTO_UDP | IPPROTO_ICMP) to send and receive IP packets can * * : ** This socket can receive IP packets destined for the local IP address of the protocol type (TCP UDP ICMP, etc.) ** Cannot: ** Received packets not destined for the local IP address (IP soft filtering discards these packets not destined for the local IP address) ** Cannot: ** You need to organize TCP, UDP, and ICMP headers when receiving packets sent from the host. You can use setsockopt to wrap your own IP header. This socket is suitable for writing a ping program.
The socket (PF_PACKET, SOCK_RAW | SOCK_DGRAM, htons (ETH_P_IP | ETH_P_ARP | ETH_P_ALL)) to send and receive Ethernet data frame. This socket is relatively powerful and can listen for all data frames on the network card
Yes: Receives frames sent to the local MAC address Yes: Receives frames sent from the local PC (the third parameter must be set to ETH_P_ALL) Yes: Receives frames sent from the local PC. ETH_P_IP 0x800 Accepts only IP frames sent to the local MAC address. ETH_P_ARP 0x806 Accepts only ARP frames sent to the local MAC address ETH_P_RARP 0x8035 Accepts only RARP frames sent to the local MAC ETH_P_ALL 0x3 Receives all TYPES of IP ARP data frames sent to the local MAC. Receives all types of data frames sent from the local machine (when promiscuous mode is enabled, non-local MAC data frames will be received)
5. Application example: Grab all IP packets (code reproduced)
#include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <linux/if_packet.h> #include <netinet/if_ether.h> #include <netinet/in.h> typedef Struct _iphdr {unsigned char h_verlen; // 4-bit header length + 4-bit IP version number unsigned char tos; // 8-bit service type TOS unsigned short total_len; //16 bits total length (bytes) unsigned short ident; // unsigned short frag_and_flags; //3 bits unsigned char TTL; //8 bits TTL unsigned char proto; //8 bit protocol (TCP, UDP or other) unsigned short checksum; // 16-bit IP header checksum unsigned int sourceIP; // 32-bit source IP address unsigned int destIP; // 32-bit destination IP address}IP_HEADER; Typedef struct _udphdr // define UDP header {unsigned short uh_sport; // 16-bit source port unsigned short uh_dport; // 16-bit destination port unsigned short uh_len; // 16-bit UDP packet length unsigned short uh_sum; // 16-bit checksum}UDP_HEADER; Typedef struct _tcphdr // define TCP header {unsigned short th_sport; // 16-bit source port unsigned short th_dport; // 16-bit destination port unsigned int th_seq; // Unsigned int th_ack; // Unsigned char th_lenres; //4 bit header length /6 bit reserved word unsigned char th_flag; // unsigned short th_win; // Unsigned short th_sum; // 16-bit checksum unsigned short th_urp; // 16-bit emergency data offset}TCP_HEADER; typedef struct _icmphdr { unsigned char icmp_type; unsigned char icmp_code; /* type sub code */ unsigned short icmp_cksum; unsigned short icmp_id; unsigned short icmp_seq; /* This is not the std header, but we reserve space for time */ unsigned short icmp_timestamp; }ICMP_HEADER; void analyseIP(IP_HEADER *ip); void analyseTCP(TCP_HEADER *tcp); void analyseUDP(UDP_HEADER *udp); void analyseICMP(ICMP_HEADER *icmp); int main(void) { int sockfd; IP_HEADER *ip; char buf[10240]; ssize_t n; /* capture ip datagram without ethernet header */ if ((sockfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)))== -1) { printf("socket error! \n"); return 1; } while (1) { n = recv(sockfd, buf, sizeof(buf), 0); if (n == -1) { printf("recv error! \n"); break; } else if (n==0) continue; // The received data does not include the data link frame header IP = (IP_HEADER *)(buf); analyseIP(ip); size_t iplen = (ip->h_verlen&0x0f)*4; TCP_HEADER *tcp = (TCP_HEADER *)(buf +iplen); if (ip->proto == IPPROTO_TCP) { TCP_HEADER *tcp = (TCP_HEADER *)(buf +iplen); analyseTCP(tcp); } else if (ip->proto == IPPROTO_UDP) { UDP_HEADER *udp = (UDP_HEADER *)(buf + iplen); analyseUDP(udp); } else if (ip->proto == IPPROTO_ICMP) { ICMP_HEADER *icmp = (ICMP_HEADER *)(buf + iplen); analyseICMP(icmp); } else if (ip->proto == IPPROTO_IGMP) { printf("IGMP----\n"); } else { printf("other protocol! \n"); } printf("\n\n"); } close(sockfd); return 0; } void analyseIP(IP_HEADER *ip) { unsigned char* p = (unsigned char*)&ip->sourceIP; printf("Source IP\t: %u.%u.%u.%u\n",p[0],p[1],p[2],p[3]); p = (unsigned char*)&ip->destIP; printf("Destination IP\t: %u.%u.%u.%u\n",p[0],p[1],p[2],p[3]); } void analyseTCP(TCP_HEADER *tcp) { printf("TCP -----\n"); printf("Source port: %u\n", ntohs(tcp->th_sport)); printf("Dest port: %u\n", ntohs(tcp->th_dport)); } void analyseUDP(UDP_HEADER *udp) { printf("UDP -----\n"); printf("Source port: %u\n", ntohs(udp->uh_sport)); printf("Dest port: %u\n", ntohs(udp->uh_dport)); } void analyseICMP(ICMP_HEADER *icmp) { printf("ICMP -----\n"); printf("type: %u\n", icmp->icmp_type); printf("sub code: %u\n", icmp->icmp_code); }Copy the code
Ethernet на самом низком уровне
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
Кто-нибудь, помогите! : |
Olej |
|
Senior Member Рейтинг (т): 8 |
Цитата klotho, 23.04.03, 15:03:59 Кто-нибудь, помогите! : Тут никто не поможет, это — к психиатру… Цитата Нужно обмениваться по сети компьютерам, которые работают под самодельной ОС (www.multex.nm.ru) Это уже начинаются настоящие «наступания на грабли» … когда говорят: «не лепите самопалки OS — не дело это!»… Всё далеко не так просто, и только начинается (вам ещё IPC предстоит!!! :-(). Что предстоит сделать с сетью: 1. Прописать стек TCP/IP в полном соответствии с RFC (в Linux, помнится передача TCP — 8000 стр. кода, а приём — 23000, кажется — это когда уже транспорт IP сделан). Почему TCP/IP (там выше фраза про NETBEUI…)? Потому, сто TCP/IP postfactum стандарт общеупотребимый, а NETBEUI etc. — это частная фирменная херня никому, кроме MS не нужная. Т.е. п.1 — прописать «транспортный уровень» 7-уровневой модели OSI. 2. Для каждого типа сетевой карты — написать драйвер, т.е. реализацию MAC-уровня для каждого типа железа (канальный уровень OSI). Это — вниз… 3. А вверх … Для минимально полноценной OS: … и вот только после всего этого … можно подумать об том, чтоб с этой OS начинать выползать в сетевое окружение… «Я скорблю вместе с вами» (с). P.S. В качестве бонуса: для попыток обмена MAC-уровня нужно начинать со стандарта NE-2000 совместимых Ethernet карт — с этого все начинают — он масово реализован и достаточно описан. Кстати, выше сказано — REALTEC карта… это кто? «Имя им легион» (с) — если RTL8029 — это и есть NE-2000, RTL8139 … всё гораздо хуже … Сообщение отредактировано: Olej — |
klotho |
|
Спасибо за ответ! Это, действительно, RTL8139, но все не так уж страшно… |
Olej |
|
Senior Member Рейтинг (т): 8 |
Цитата klotho, 23.04.03, 15:50:08 А где посмотреть структуру MAC-заголовка? MAC пакет — для вашей платы — это Ethernet кадр. Цитата Я просто с сетями возился до сих пор только на уровне сокетов в Delphi… А первое с чего нужно начать — уровень абстракции сокетов, особенно Delphi — забыть: это всё уже использование надстроек, которые только предстоит построить. P.S. А если уже и вправду — невмоготу … я бы сделал так: Вот теперь можно с tcpdump: |
klotho |
|
Я написал драйвер RTL8139, мне нужно теперь передавать пакеты из Windows в мои вычислители. А можно ли под Win98 выдавать «сырые» пакеты на уровне MAC-адресов? |
Oksiv |
|
2klotho — могу сказать одно, когда я писал драйвер USB устройства + USB host P.S почитал про MULTEX, интересно, а драйвер для USB хоста не думали написать, в принципе могу поучаствовать? |
Olej |
|
Senior Member Рейтинг (т): 8 |
Цитата klotho, 28.04.03, 13:13:34 Я написал драйвер RTL8139, мне нужно теперь передавать пакеты из Windows в мои вычислители. А можно ли под Win98 выдавать «сырые» пакеты на уровне MAC-адресов? RAW-сокет — это уже сокет IP, но … незаполненный. Т.е. для его использования уже нужен (полноценный!) транспортный уровень IP! Сокет MAC-уровня есть пока реализованный только в Linux — тип SOCK_PACKET (так, кажется). Может там, в кодах смотреть надо. Если уж совсем не ймётся туда лезть — смотрите книгу У.Стивенса, вот здесь об ней: |
Oksiv |
|
Цитата Olej, 30.04.03, 12:18:04 RAW-сокет — это уже сокет IP, но … незаполненный. Т.е. для его использования уже нужен (полноценный!) транспортный уровень IP! Сокет MAC-уровня есть пока реализованный только в Linux — тип SOCK_PACKET (так, кажется). Может там, в кодах смотреть надо. Если уж совсем не ймётся туда лезть — смотрите книгу У.Стивенса, вот здесь об ней: RAW сокеты есть и в Windows 2000. |
Olej |
|
Senior Member Рейтинг (т): 8 |
Цитата ViSko, 30.04.03, 14:01:08 RAW сокеты есть и в Windows 2000. Нет, я имел в виду именно сокет MAC-уровня, т.е. сокет Ethernet-кадра (или другой среды…), именно AF-PACKET в Linux его и определяет. То-же, с чем оперирует перехват пакетов в BPF (Berkley Packet Filter) & tcpdump. |
Oksiv |
|
У Стивенса есть… <br> до этого я ещё не дочитал |
Olej |
|
Senior Member Рейтинг (т): 8 |
Цитата ViSko, 05.05.03, 17:02:40
У Стивенса есть… <br> до этого я ещё не дочитал љ:) fd = socket( AF_INET, SOCK_PACKET, htons( ETH_P_ALL ) ); — странно мне только (но в Linux многое «по-быстренькому») — почему сокет для MAC-уровня должен определяться в семейсиве адресов IP? |
Balamut |
|
Junior Рейтинг (т): 0 |
сырцы для Ethernet&TCP/IP смотреть на |
Olej |
|
Senior Member Рейтинг (т): 8 |
Кстати, то, что я писал: Цитата fd = socket( AF_INET, SOCK_PACKET, htons( ETH_P_ALL ) ); — это специфика Linux, и никого более. А вот в хэдерах стандартной BSD реализации стека TCP/IP определено ещё такое адресное семейство как AF_LINK — т.е. судя по всему — это MAC-уровень, и они его сами в реализации для этого используют. Нельзя ли этой штукой попользоваться с пользовательского уровня? И ещё одна штука, общеупотребимая (портированная) — это BPF (Berkley Packet Filter). Обычно, его знают в связи с снифером tcpdump, но это гораздо большее — он имеет описанный пользовательский интерфейс, вполне достаточный для манипулирования с сетью минуя стек TCP/IP (или параллельно — потому он и «фильтр»), в том числе и на MAC-уровне, что мы и видим по tcpdump. |
Andy_user |
|
Member Рейтинг (т): 3 |
Обычно использую в Linux (2.4.3-20mdk): По поводу BPF: Сообщение отредактировано: Andy_user — |
Olej |
|
Senior Member Рейтинг (т): 8 |
Цитата Andy_user, 21.05.03, 16:58:21 Обычно использую в Linux (2.4.3-20mdk): По поводу BPF: Засомневался … и специально проверил: — запись в канальный уровень через BPF используется очень редко: UDP/TCP пишутся через IP-сокет, ICMP/IGMP — через RAW … почти ничего не остаётся… Поэтому запись в BPF менее известна и освещена. Но — напр. демон RARP-разрешителя во многих OS не сделан в ядре (см. ниже), а как пользовательский процесс пишет в BPF. Запись в BPF — незаменимая штука, когда нужно отправлять «хитрые» UDP/TCP сегменты — если вы помните, там такая штука: UDP/TCP пакеты не доходят (!) до RAW-сокета — они известны ядру, оно их принимает, и не передаёт RAW… — почему я и засомневался, что есть такая известная библиотека libcap — интерфейс к … чуть не сказал BPF — это «»обобщённый» интерфейс, который использует «то что есть»: BPF, пакетный сокет Linux, что-то ещё из TLI SVR4…. — BPF — считается много эффективнее, чем пакетный сокет Linux, и тем-более всякая самопальная фича, типа «сниферов»: |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Сетевые Технологии
- Следующая тема
[ Script execution time: 0,0383 ] [ 15 queries used ] [ Generated: 14.05.25, 07:57 GMT ]