Python - OSError in sendto(bytes, (ip,port)) - python

I'm currently having a lot of trouble while writing a raw socket.
While my implementation is pretty big by now, i think solving the problem for the following code, would also solve it for my whole implementation:
from scapy.all import *
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
src_port = 12345 # any random port > 1024 i guess ...
dst_port = 80 # should be tcp, as http runs over it in the end
dst_addr = socket.gethostbyname("www.google.de")
# ensuring that kernel will not create its own ip header
sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, True)
# create a packet to send using scapy
packet = IP(dst = dst_addr)/TCP(dport = dst_port)
sock.sendto(bytes(packet), (dst_addr, 80))
I get the following error :
OS error: [Errno 22] Invalid argument
which is raised by:
sock.sendto(bytes(packet), (dst_addr, 80))
Does someone have a clue, why this is not working?
-- EDIT --
I'm working on MacOSX.
I already noticed this question: Raw sockets and sendto in python
However, I'm hoping that someone has an answer anyways, as the old question lacks a good answer and is also around 4 years old.

Related

Python Socket strange IP connection from outside

A little summary, i programm a socket server in python to fetch data from my MSSQL database and send it to my Flutter App. So far so good. Now i tried to test it from outside. I set a Port Forwarding and tried to connect it. btw it works fine. I let the server run for few hours and now i get a error messenge.
See the pic, the first ip is mine but the second is not.
Someone is trying to connect to my server. How do solve this Problem
MY Python Code
from datetime import datetime
import socket
from SqlServerRequest import SqlServerRequest
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.43.126', 2222))
s.listen(5)
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established.")
data = clientsocket.recv(2048).decode()
print(data)
if data == "open":
o = SqlServerRequest.dataForOpenOrders()
clientsocket.sendall(bytes(o,"utf-8"))
if data == "closed":
c = SqlServerRequest.dataForClosedOrders()
clientsocket.sendall(bytes(c,"utf-8"))
clientsocket.close()
Well, you did set up port forwarding to allow anyone on the internet to connect to your machine. Someone just did, and sent something to your program that it didn't expect, and your program crashed.
That's a great lesson on making your program robust in the face of unexpected input, for instance.
Secondly, if you want your program to actually be accessible on the internet, you will probably want some sort of authentication -- for instance, a password known by your Flutter client.
Likely on top of that, you'd want some sort of transport-layer security so people can't read your data in-flight.
The crash happens because you're trying to convert to Unicode. If this is really all there is, then it's silly to convert to Unicode at all. Just leave it as a bytes string.
wwhile True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established.")
data = clientsocket.recv(2048)
print(data)
if data == b"open":
o = SqlServerRequest.dataForOpenOrders()
clientsocket.sendall(bytes(o,"utf-8"))
if data == b"closed":
c = SqlServerRequest.dataForClosedOrders()
clientsocket.sendall(bytes(c,"utf-8"))
clientsocket.close()

Scapy, Socket and 3-way-handshake

I'm trying to do a pretty weird thing with Python/Scapy/Socket (Linux env). I'd like to manage the 3-way handshake and then go back to the usual "socket" management.
Here is what I did:
import socket
from scapy.all import *
pkt = IP(src='192.168.1.2',dst='192.168.1.1')/TCP(sport=12345,dport=44144,flags='S',seq=1000)
SYN = bytes(pkt)
outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
outs.connect(('192.168.1.1',44144))
outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
outs.sendto(SYN, ('192.168.1.1', 0))
raw_buffer = outs.recv(4096)
buffer = IP(raw_buffer)
my_ack = buffer.seq + 1
pkt=IP(src='192.168.1.2',dst='192.168.1.1')/TCP(sport=12345, dport=44144, flags='A', seq=1001, ack=my_ack)
ACK=bytes(pkt)
outs.sendto(ACK, ('192.168.1.1', 0))
So far so good, the connection is established. Then I try to use the socket and the created connection with the usual "send" method:
outs.send(bytes('AAA','utf8'))
At this point I get an error:
*** OSError: [Errno 22] Invalid argument
So, what I'm trying to do is to switch back from a RAW_SOCKET to a system handled one. Is that possible in some ways?
Thanks,

Can socket receive infinite data stream python?

While trying to attempt to go for python based socket, I have 2 questions which I am not able to resolve. Kindly help me. Here is my sample socket code:
import socket
import threading
import chardet
bind_ip = '0.0.0.0'
bind_port = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(1) # max backlog of connections
print (('Listening on {}:{}').format(bind_ip, bind_port))
def handle_client_connection(client_socket):
request = client_socket.recv(4096 )
result = chardet.detect(request)
print(result)
print (request.decode(result['encoding']))
client_socket.send('ACK!'.encode(result['encoding']))
client_socket.close()
while True:
client_sock, address = server.accept()
print (('Accepted connection from {}:{}').format(address[0], address[1]))
client_handler = threading.Thread(
target=handle_client_connection,
args=(client_sock,) # without comma you'd get a... TypeError: handle_client_connection() argument after * must be a sequence, not _socketobject
)
client_handler.start()
The above one is server and the below is client:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 9999))
client.send(str('test data').encode("utf-16"))
response = client.recv(4096)
print(response.decode("utf-16"))
Now the questions:
1) What is the meaning of the number in this statement: client.recv(4096)? What is 4096, is it bit or byte of kilobyte for data receiving?
2) Can I receive infinite data stream through the socket? Meaning, as this statement client.recv(4096), whatever is the menaing of 4096, may be byte, then the socket will receive the 4096 bytes of data only. I do not have a control on the size of data received through the socket, hence, can I generalize it to accept any size of data through socket?
Please help me get the answers to above queries. I tried the python documentation for socket but didn't found much. I guess I miss something. Please help me get through it.
According to documentation
"If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from."
found here
"https://linux.die.net/man/2/recv"
which was from python 3.6 docs
"he maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2)"
found here
"https://docs.python.org/3.6/library/socket.html"
so it is a bytes object and it may actually truncate the message depending on the protocol. So message integrity is handled by the next layer up. So presumably you would loose part of a UDP packet, and you would get either a retry or an additional packet for TCP if the message was too large to fit in the buffer.

PYTHON - UDP listening without knowing the server

using python2.X (for Linux (++) and Windows (+))
I'm trying to create a python client, to listen to an adress and a port.
The messages are sent by an app on a specific adress and a specific port, but I don't know how it is written. I'm just sure it is functionnal and it uses UDP protocole.
So, I've written this code to receive the messages :
import socket
#---socket creation
connexion = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#---Bind
try:
connexion.bind(('', 10015))
except socket.error:
print "connexion failed"
connexion.close()
sys.exit()
#---testing
while 1:
data, addr = connexion.recvfrom(1024)
print "messages : ", data
At this point, there is no error running it, but the code stops at this line :
data, addr = connexion.recvfrom(1024)
and nothing happens... I think I'm not connected and can't receive messages but I don't know why.
I tried to change the adresse by : '192.168.X.X', but it's the same.
If anyone could help me, that would be great. I'm not very comfortable why python...
PS : sorry for my english.
I found my problem. I changed the IP adress (in the documentation, it was 192.168. 00 8. 0 15 ; I tried whithout the zeros like a normal adress (192.168.8.15) and I received my messages
I changed the structure of my code too : (don't know if it has impact) I put my "try: [...] except:[...]" on the line
data, addr = connexion.recvfrom(1024)
instead of the line :
connexion.bind(('', 10015))
Thanks for helpping ;)
Your code is all well and fine. You can verify that it works using the following Python snippet:
import socket
connexion = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
connexion.sendto("sending data via udp", ("localhost", 10015))
If a message send with this snippet is not displayed, check your firewall. To investigate whether (or what) your other application is actually producing try using tcpdump or wireshark.

python raw socket: Protocol not supported

I am trying to open a raw socket with Python under linux.
My simple code:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 5454))
And I got this error:
[ERROR] Protocol not supported
By the way, I am using python 2.7.3 under linux 12.04, and I used root to run the code.
Does anyone have a clue?
Update: The solution given by dstromberg is correct. If you want the whole packet, then use his solution. However, there is another combination:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
that also works.
In this case, you will receive a whole TCP packet with IP and TCP headers on it.
If your use dstromberg's solution, you will also see the ethernet header. So it depends on how 'raw' you want your packet to be.
Try socket.AF_PACKET instead of socket.AF_INET.
This runs without error as root:
#!/usr/local/cpython-3.3/bin/python
import socket as socket_mod
#s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
socket = socket_mod.socket(socket_mod.AF_PACKET, socket_mod.SOCK_RAW, socket_mod.IPPROTO_IP)
#socket.bind(('localhost', 5454))
socket.bind(('lo', 5454))
Try socket.AF_UNIX, it can solve your problem, good luck.

Categories