Color
@Color
Golang SWE, Cloud & DevOps

Как запустить http сессию в Python через SOCKET_RAW?

Мне необходимо использовать сырые сокеты для приема GET-запроса и ответа на него.
Сначала реализовал это через SOCK_STREAM, но не знаю как сделать через SOCK_RAW.

Вот как выглядит сервер, пока он только ловит пакеты, но не отвечает:

import socket
import struct

act_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

for x in range(10):
    print x
    response, addr = act_socket.recvfrom(65535)
    if not response:
        break
    elif addr[0] == '127.0.0.1':         
        #take first 20 characters for the ip header
        ip_header = response[0:20]
         
        #now unpack them
        iph = struct.unpack('!BBHHHBBH4s4s' , ip_header)
         
        version_ihl = iph[0]
        version = version_ihl >> 4
        ihl = version_ihl & 0xF
         
        iph_length = ihl * 4
         
        ttl = iph[5]
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8]);
        d_addr = socket.inet_ntoa(iph[9]);
         
        print 'Version : ' + str(version) + ' IP Header Length : ' + str(ihl) + \
        ' TTL : ' + str(ttl) + ' Protocol : ' + str(protocol) + \
        ' Source Address : ' + str(s_addr) + ' Destination Address : ' + str(d_addr)

        tcp_header = response[iph_length:iph_length+20]
     
        #now unpack them
        tcph = struct.unpack('!HHLLBBHHH' , tcp_header)
         
        source_port = tcph[0]
        dest_port = tcph[1]
        sequence = tcph[2]
        acknowledgement = tcph[3]
        doff_reserved = tcph[4]
        tcph_length = doff_reserved >> 4
         
        print 'Source Port : ' + str(source_port) + ' Dest Port : ' + \
        str(dest_port) + ' Sequence Number : ' + str(sequence) + ' Acknowledgement : ' + \
        str(acknowledgement) + ' TCP header length : ' + str(tcph_length)

        h_size = iph_length + tcph_length * 4
         
        #get data from the packet
        data = response[h_size:]
        
        print "lenth of data: ", len(response), "required: ", h_size
        print 'Data : ' + data


Вот что делает клиент (получение ответа пока убрал):

import socket
import httplib

host = "127.0.0.1"
port = 8080

httpServ = httplib.HTTPConnection(host, port)
httpServ.connect()

httpServ.request('GET', "mysite.com?addr=index.html")

# response = httpServ.getresponse()
# if response.status == httplib.OK:
#     print "Output from HTML request"
#     print response.read()

httpServ.close()

Сейчас клиент отправляет пакеты, но получает ошибку
socket.error: [Errno 111] Connection refused
при попытке соединиться (httpServ.connect())

Вопросов два:
1. Как должно быть реализован обмен пакетами между клиентом и сервером, использую сырые пакеты на сервере; нужно ли реализовывать тройное рукопожатие?
2. Сервер принимает только ip и tcp заголовок, данных нет. В чем ошибка?
  • Вопрос задан
  • 3232 просмотра
Решения вопроса 1
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Ух, знаете вы, батенька, толк в извращениях то...

Коль уж вы решили работать с TCP, то вам придется реализовать полностью этот протокол (сборка/проверка/распаковка пакетов, установление соединения (как раз таки handshake) и т.д.). Если вам не важна производительность, можно не реализовывать контроль насыщением и прочие приблуды. а посылать следующий пакет только по подтверждению доставки предыдущего. Но это будет оооочень медленно работать.

По поводу того что сервер принимает только ip и заголовок - так а вы уверены что там должны быть данные? В любом случае рекомендую глянуть на реализацию простенького снифера: вот.

p.s. А почему именно RAW сокеты то?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы