python bind to interface and port on windows - python

My computer having 2 NICs: one with 1.1.1.1 while the other with some internal network.
I've some strange behavior while binding to ip and port:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('1.1.1.1',1234))
sock.settimeout(0)
group= socket.inet_aton('224.1.1.1')
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
print("Listening at:" + str(sock.getsockname()))
time.sleep(2)
while True:
print("\waiting to receive message")
data, address = sock.recvfrom(1024)
print ("received {} butes from {}".format(len(data), adsress))
print (data)
On print("Listening at:" + str(sock.getsockname())) I'm getting the expected data (i.e interface 1.1.1.1 and port 1234).
On print ("received {} butes from {}".format(len(data), adsress)) I'm getting data from other interface
Any idea what is going on?

Related

Read Brodcast (ff02::1) msg python socket

i have this code to read a msg from a client.
import socket
# UDP_IP = 'fd53:7cb8:383:2::10'
UDP_IP = '::'
UDP_PORT = 13400
# create socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# bind the socket
server_add = (UDP_IP, UDP_PORT)
print('starting up on {} on port {}'.format(*server_add))
sock.bind(server_add)
while True:
print('waiting msg')
data, addr = sock.recvfrom(1024)
print("received message:", data)
print("addr is", addr)
sock.close()
break
the client IP is : 'fd53:7cb8:383:2::c9'
the Server IP is : 'fd53:7cb8:383:2::10'
i can saw the msg on wireshark
No.
Time
Delta
Source
Destination
Protocol
Length
70
6.516768
3.631930
fd53:7cb8:383:2::c9
ff02::1
DoIP
103
but the sock.recvfrom(1024) is not getting anything

Spoofing IP address on same machine running 127.0.0.1 server

I am hosting a server listening for UDP packets on local host with IP address '127.0.0.1'. On the same machine, how would I be able to send packets to this server with spoofed IP address '1.2.3.4' and not '127.0.0.1'?
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
if __name__ == "__main__":
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
sizes = {}
for size in range(512):
sizes[size] = 0
while True:
data, addr = sock.recvfrom(8092)
if addr[0] != "1.2.3.4":
print("Acess denied")
#print(addr[0])
#print(len(data))
continue
else:
print("hello")
print ("length:", len(data))
sizes[len(data)] += 1
Currently this is the code I am using to send UDP packets.
import socket
import ipaddress
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
if __name__ == "__main__":
ipaddress.ip_address(unicode('1.2.3.4', "utf-8"))
Message = "H"
clientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
clientSock.sendto(Message, (UDP_IP, UDP_PORT))

How can I bind more than one IP without using multithreading?

I'm wondering if it's possible to bind more than one multicast address without using multithreading(creating few sockets), just by creating one socket that can obtain data from two addresses (which is my current way of doing this).
My code looks like:
import socket
import struct
import time
MCAST_GRP2 = '239.0.1.105'
MCAST_GRP = '239.0.1.104'
MCAST_PORT = 12345
IS_ALL_GROUPS = True
#scan time in seconds
SCAN_TIME = 10
#sampling time in seconds
SAMPLING_TIME = 1
bufferUDP = 2048
totalSize = 0
bitrateList = []
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if IS_ALL_GROUPS:
# on this port, receives ALL multicast groups
sock.bind(("", MCAST_PORT))
sock2.bind(("", MCAST_PORT))
else:
# on this port, listen ONLY to MCAST_GRP
sock.bind((MCAST_GRP, MCAST_PORT))
sock2.bind((MCAST_GRP2, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
mreq2 = struct.pack("4sl", socket.inet_aton(MCAST_GRP2), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
sock2.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq2)
print("_____.:| Starting analysis of multicasts! |:._____\n")
for x in range(SCAN_TIME):
stop = time.time() + SAMPLING_TIME
while (time.time()<stop):
totalSize += len(sock.recv(bufferUDP)) + len(sock2.recv(bufferUDP))
bitrateList.append(totalSize)
print(bitrateList[x]*8/(1000000))
totalSize = 0
bitrateList.pop(0)
txtfile = open("Bitrate_history_ip_{}.txt".format("TESTTT"),"w+")
for x in range(SCAN_TIME-1):
bitrateList[x] = bitrateList[x]*8/(1000000)
txtfile.write("{}.Bitrate was equal to: {} Mbps\n".format(x+1,bitrateList[x]))
txtfile.write("Maximum bitrate value was: {} Mbps\n".format(max(bitrateList)))
txtfile.write("Minimum bitrate value was: {} Mbps\n".format(min(bitrateList)))
print('End of test')
time.sleep(5)
And is based on:
How do you UDP multicast in Python?
.. just by creating one socket that can obtain data from two addresses
One cannot bind a socket to multiple IP addresses.
One can still handle multiple sockets in parallel without needing multiple threads or multiple processes. This is done with an event-based architecture and non-blocking sockets, see Non-blocking Sockets in the Python documentation for more details.

Sending JSON object to a tcp listener port in use Python

I have a listener on a tcp localhost:
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def client_socket():
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP,TCP_PORT))
s.listen(1)
while 1:
print 'Listening for client...'
conn, addr = s.accept()
print 'Connection address:', addr
data = conn.recv(BUFFER_SIZE)
if data == ";" :
conn.close()
print "Received all the data"
i=0
for x in param:
print x
#break
elif data:
print "received data: ", data
param.insert(i,data)
i+=1
#print "End of transmission"
s.close()
I am trying to send a JSON object to the same port on the local host:
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def json_message(direction):
local_ip = socket.gethostbyname(socket.gethostname())
data = {
'sender' : local_ip,
'instruction' : direction
}
json_data = json.dumps(data, sort_keys=False, indent=2)
print("data %s" % json_data)
send_message(json_data)
return json_data
def send_message(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(data)
data = s.recv(1024)
print('Received', repr(data))
However, I get a socket error:
socket.error: [Errno 98] Address already in use
What am I doing wrong? Will this work or do I need to serialize the JSON object?
There are a few problems with your code, but the one that will likely address your issue is setting the SO_REUSEADDR socket option with:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
after you create the socket (with socket.socket(...) but before you attempt to bind to an address (with s.bind().
In terms of other things, the two "halves" of the code are pretty inconsistent -- like you copied and pasted code from two different places and tried to use them?
(One uses a context manager and Python 3 print syntax while the other uses Python 2 print syntax...)
But I've written enough socket programs that I can decipher pretty much anything, so here's a working version of your code (with some pretty suboptimal parameters e.g. a buffer size of 1, but how else would you expect to catch a single ;?)
Server:
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
BUFFER_SIZE = 1
def server_socket():
data = []
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST,PORT))
s.listen()
while 1: # Accept connections from multiple clients
print('Listening for client...')
conn, addr = s.accept()
print('Connection address:', addr)
while 1: # Accept multiple messages from each client
buffer = conn.recv(BUFFER_SIZE)
buffer = buffer.decode()
if buffer == ";":
conn.close()
print("Received all the data")
for x in data:
print(x)
break
elif buffer:
print("received data: ", buffer)
data.append(buffer)
else:
break
server_socket()
Client:
import socket
import json
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8192 # The port used by the server
def json_message(direction):
local_ip = socket.gethostbyname(socket.gethostname())
data = {
'sender': local_ip,
'instruction': direction
}
json_data = json.dumps(data, sort_keys=False, indent=2)
print("data %s" % json_data)
send_message(json_data + ";")
return json_data
def send_message(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(data.encode())
data = s.recv(1024)
print('Received', repr(data))
json_message("SOME_DIRECTION")

RAW socket UDP Multicast in IPv6

i receive data from multicast for my UDP sniffer, but only in IPv4.
My code looks like this,
try:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
except socket.error as msg:
print('Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
mreq = struct.pack("4sl", socket.inet_aton('239.255.11.3'), socket.INADDR_ANY)
# receive a packet
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
packet = s.recvfrom(65000)
But i am receiving data only when i set IPv4 address, and i want also receive from IPv6 multicast address.
I will be really grateful for any ideas and sorry for my english. ;-)
this example gets a multicast on FF02::158 (IoTivity UDP CoAP) in Windows
import socket
import struct
address = ('', 5683)
interface_index = 0 # default
sock = socket.socket(family=socket.AF_INET6, type=socket.SOCK_DGRAM)
sock.bind(address)
for group in ['ff02::158']: # multiple addresses can be specified
sock.setsockopt(
41, # socket.IPPROTO_IPV6 = 41 - not found in windows 10, bug python
socket.IPV6_JOIN_GROUP,
struct.pack(
'16si',
socket.inet_pton(socket.AF_INET6, group),
interface_index
)
)
while True:
data, sender = sock.recvfrom(1500)
while data[-1:] == '\0': data = data[:-1]
print(str(sender) + ' ' + repr(data))
fuller answer
https://stackoverflow.com/a/66943594/8625835
You need to use the sockopt IPV6_ADD_MEMBERSHIP, as the API between IPv6 and IPv4 is slightly different. This is a good example.
This is what I'm doing in my code:
mc_address = ipaddress.IPv6Address('ff02::1:2')
listen_port = 547
interface_index = socket.if_nametoindex('eth0')
mc_sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
mc_sock.bind((str(mc_address), listen_port, 0, interface_index))
mc_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP,
struct.pack('16sI', mc_address.packed, interface_index))
This is for a DHCPv6 server, but you'll get the idea.
If you also want to get multicast packets transmitted by yourself you have to add:
mc_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)

Categories