Difference between C# and Python UDP Examples [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
You can find this C# UDP example in various forms in many places.
UdpClient udpc = new UdpClient(55001);
IPEndPoint iep = new System.Net.IPEndPoint(IPAddress.Parse("192.168.1.100"), 55001);
byte[] data = udpc.Receive(ref iep);
string req = Encoding.ASCII.GetString(data);
When I run portqry, I find that it responds to 127.0.0.1, but not 192.168.1.100.
PortQry.exe -n 192.168.1.100 -p udp -e 55001
I tried this also using the raw socket interface. I could only get it to work if I bind to 127.0.0.1 and PortQry the same.
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 55001);
Socket sock = new Socket(ipe.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
byte[] buffer = new byte[1024];
sock.Bind(ipe);
sock.Receive(buffer);
string req = Encoding.ASCII.GetString(buffer);
When I run the Python UDP receiver example using port 192.168.1.100, I find it responds to 192.168.1.100, but not 127.0.0.1.
On another machine, I have a route added so that traffic to 192.168.1.100 goes out to the router and then returns. In wireshark, using the Python server, I see a packet go out to the router and one come back when I PortQry 192.168.1.100. Doing the same with the C# example, the packet does not return.
What is different? The wireless and VPN adapters are off; so, there should only be one interface being used. I would like to have the behavior I'm seeing in Python in C# so I can see the traffic from WinPcap.
I have some additional info. I've tried this with the underlying winsock library using this exact code except to change the IP and port. The problem is the same. I can receive only on the loopback. I've verified the port is being listened to on 192.168.100 using netstat. I've also discovered the python receive example will accept UDP traffic even when I physically disconnect Ethernet and ipconfig shows no IP at all.

Your code doesn't tell the UdpClient what IP address to use. The IPEndPoint you create isn't actually used anywhere. You should use it to listen on that IP:
IPEndPoint iep = new System.Net.IPEndPoint(IPAddress.Parse("192.168.1.100"), 55001);
UdpClient udpc = new UdpClient(iep); // Set the IP and port
iep = ip = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udpc.Receive(ref iep); // This returns the remote IP and port in iep
string req = Encoding.ASCII.GetString(data);
This way you receive on a specific host and port and not only on the loopback address.

Related

How to capture martian packets without letting the linux kernel to drop them and then catching them using raw sockets

I'm trying to setup a network to simulate an Edge computing scenario with LTE. But the question here is more pertaining to IP tables and raw sockets on the server.
I have the following setup:
PC-A is the Tower, PC-C is the LTE Core, PC-B is acting as intermediary and routing data using proxy ARPs
Cell phone wants to connect to a TCP server on PC-B(IP: 172.17.1.3)
Cell phone(IP:192.172.0.2) sends packets to PC-A(IP: 172.17.1.1)
The data from PC-A(172.17.1.1) generally has to reach LTE-EPC on 172.17.1.4 which is connected via PC-B(172.17.1.2 - 172.17.1.3 with proxy ARPs). And the data comes in the form of UDP packets to PC-B(IP: 172.17.1.2)
I use NAT table and python script with raw sockets to send all of these UDP packets to a local port, do some filtering, decapsulate the GTP headers and send the TCP/IP packet to the TCP server on PC-B interface(172.17.1.3). I use the below iptables settings to do this
iptables -t nat -A PREROUTING -p udp -d 172.17.1.4 --dport 2152 -j DNAT --to-destination 172.17.1.2:7000
Until here everything works, the extracted TCP/IP packet also reaches the TCP server on 172.17.1.3. The server responds to these packets. For example, for the SYN packet from the cell phone, the server now sends out SYN, ACK. However, the server responds to the original source address 192.172.0.2.
I want to catch these response TCP/IP packets from the TCP server 172.17.1.3 to 192.172.0.2 and do some GTP encapsulation before sending them back to PC-A.
Can anyone tell me how I can use the iptables to tell the kernel to stop dropping these martian packets with destination address 192.172.0.2, but instead forward to a local ip and port, so I can read the same.
I can see the SYN, ACK responses from the server on wireshark. But I assume that these are dropped as I already tried to route it to local ip:port using a similar iptables rule from above.
Any help is much appreciated, Thank you.
It sounds like a tun/tap interface could be useful here. Here's the official Linux kernel documentation.
Both these interface types allow a program to create a virtual network interface. This is designed for tunnels and VPNs and it seems like that is exactly what you are creating.
According to the linked documentation, you may create an interface by opening /dev/net/tun (O_RDWR) and issuing this ioctl to initialize it:
struct ifreq req;
memset(&req, 0, sizeof(req));
req.ifr_flags = IFF_TUN; // or IFF_TAP
strncpy(req.ifr_name, "tunnel%d", IFNAMSIZ); // optional; leave it blank to get a default name; you don't have to have a %d
ioctl(fd, TUNSETIFF, &req); // error check omitted for demonstration
// req.ifr_name now contains the name that was actually selected
After the ioctl you have a virtual network interface in your system. You can configure IP addresses, routes, whatever.
Any time the kernel sends a packet out through your interface it will go into a queue and you'll be able to read it. Any time you write to the interface the kernel will process it as if it's a real packet that just arrived.
You will need to configure networking like it's a real interface. Set up a static route so that 192.172.0.0/16 (or whatever your subnet is) is reached through the tunnel interface. I'm not sure if Linux will let you do this without giving it an address; you might have to give it a dummy address like 192.172.255.254. Or a completely unrelated address like 1.2.3.4 and then let Linux think there's another router in front of your cellphone subnet. Or maybe it will just work without an address - not sure.
The difference between "tun" and "tap" is whether Ethernet processing happens or not (IP tunnel vs Ethernet tap). I expect tun is right for your application. If you choose tap then Linux will also use ARP and so on, and the interface will certainly need an address.
You might find it convenient to use the tunnel interface in both directions, or just one. IP packets aren't required to take the same route in both directions. This is the "correct" way to implement a tunnel, so you might find that a lot of mysterious bugs go away by using it.

How can I send some udp via python to a web domain?

So currently I am trying to send udp to a server with a web domain like this
www.example.com/path?stuff=exist
I am currently trying to use socket
and this is is an example of my code
import socket
IPADDR = '64.233.177.139'
that is the ip of google, and not the ip I am currently trying to send to
PORTNUM = 9001
PACKETDATA = '42["message","test"]'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
s.connect((IPADDR, PORTNUM, '/path?stuff=exist'))
s.send(PACKETDATA)`
And I currently get this error
TypeError: getsockaddrarg() takes exactly 2 arguments (3 given)
I am new to using the socket library and did some digging to no avail.
For some more context I just want to send the data in PACKETDATA to the server google.com/path?stuff=exist (not really that url, just an example)
Anything helps, thanks in advance.
Your immediate programming problem is that socket.connect expects to be called with an argument that is a tuple containing exactly two items -- a hostname (or IP address) string and a port number. But this program passes an argument tuple that contains 3 items -- a host address, a port number and the string '/path?stuff=exist'. That's why the error message complains about finding 3 things where only 2 were expected.
If you want to send '/path?stuff=exist' over UDP then you'll have to include it in the data portion of the datagram. You'll also have to come up with some way of making it distinguishable from the PACKETDATA that you're already putting into the datagram body. (That doesn't need to be fancy. You could just insert a space between the path string and the PACKETDATA.)
There might also be a conceptual problem here. A web server only listens for TCP traffic. It does not listen for UDP traffic. So unless you've arranged for your specific server to have some sort of listener accepting datagrams on the target UDP port, nothing at the server side will collect this traffic even after you've figured out how to get Python to send it.

Python raw socket doesn't see outgoing data

I use the following code to create a raw socket : http://pastebin.com/pmg9iKgG
As you can see, i want :
all TCP received packet send from port 5555 of a server to my PC,
all TCP send packets from my PC to port 5555 of a server.
The problem is : i'm only able to see incoming packets, not outgoing packets. This is quite annoying for a sniffer...
Could you help me with this?
I'm using Anaconda as python distro (3.6, x64), on windows 10. wireless (intel) or ethernet (through USB adapter cause slim laptop).
I've search the internet and i haven't seen any problem like that. Moreover, MSDN says that it should work in both way (outgoing and incoming) : https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548%28v=vs.85%29.aspx
One common use of raw sockets are troubleshooting applications that need to examine IP packets and headers in detail. For example, a raw socket can be used with the SIO_RCVALL IOCTL to enable a socket to receive all IPv4 or IPv6 packets passing through a network interface. For more information, see the SIO_RCVALL reference.
I would appreciate any help with this )))
Just on thing :
i bypass this line of code :
host = socket.gethostbyname(socket.gethostname())
by :
host = "192.168.0.29"
cause it's not the right value (but that's not the problem, moreover the methode socket.getfqdn() does the job, but i didn't updated my script)
EDIT : it was the windows FW that caused this strange behaviour, by deactivating some filter, i was able to see all incoming and outgoing packets.

Can sockets be used to connect multiple computers on different networks in python? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have been looking all over the internet for an answer but haven't been able to find one as of now. I am extremely new to networking so please do accept that I hardly know anything about it. I am able to send data to and from computers on a LAN network using sockets but I want to know if it is possible to connect to a computer at my friends house per say and send data to and from our computers solely using sockets (no telnet or netcat servers). Or is this impossible and should I be looking at a different python library or should I set up some sort of server which both machines would connect to?
Any help would be greatly appreciated and please take into account that I am new to this...
Sockets should work, but there are some caveats:
If the server (assuming you are using TCP sockets) is behind a firewall or NAT (typically if you have a router) you will need it to be configured to redirect the port on the public interface (visible from the Internet) to the local port.
You will need to know your friend's public IP or hostname to connect to them.
If your networks look like this:
+---------------+ +-----------+ +--------+ +---------------+ +------------------+
| Your computer |-->|Your router|-->|Internet|-->|Friend's router|-->|Friends's computer|
+---------------+ +-----------+ +--------+ +---------------+ +------------------+
192.168.0.5 host.isp.com friend.isp.com 192.168.2.55
And your friend is running the server on his local network, on port 9000 (for example), then you'd connect to friend.isp.com:9000. If their router is configured to redirect traffic on port 9000 on the friend.isp.com interface (internet) to 192.168.2.55 (local machine) then a connection should be established correctly.
It is possible but it will require some configuration on the router of your friend. The reason is that nowadays everybody has a public IP address that is provided by your service provider. This IP address is not fixed per se, but it is easy to lookup what is the current IP# https://www.whatismyip.com/
Now sending is not going to be a problem, but receiving is. Some service providers like here in Belgium Telenet don't allow just any port to be used and you have to find out which ports are allowed. The well known ports are most likely not allowed. That for instance makes it impossible to host a webserver without first contacting your ISP. Port 10000 for instance will work. Contact your ISP to find out these kind of limitations.
Next problem is that your both have a router and a private network with private IP# behind a NAT/PAT enabled router. For instance if I do ipconfig on my pc I get following IP# 192.168.1.99. This IP# is unique behind my router, but it is not unique on the whole internet so these IP# cannot be used directly when communicating over the internet. So the router is going to use NAT/PAT and some lookup table that is filled based on the outgoing packets. You send something, the nat/pat table is build, your private IP# is replaced with the public one and an allocated port. When a reply comes to you the port is used to change it back to the IP# of the original request. For this reason sending is not a problem but receiving is.
To solve this problem your friend has to setup port forwarding or put a pc in a demiliterized zone, it depends on the router in question. Port forwarding is like manually filling the NAT/PAT table with an entry. If something arrives on this port, send it to that private IP# using that port.
Next problem on both sending and receiving machines is the firewall. The firewall has to be switched off or configured to allow outgoing and incoming traffic on the ports that you are planning on using.
If you understand all that then you can make it work. But if this is all Chineze to you, then you will have a lot of difficulties to make it work.
So conclusion is that it is possible but there are quite some caveats to tackle.
There are many questions of people that are trying to do exactly what you describe here and have a lot of trouble making it work. If you are really a novice I would try to find somebody with experience or you will lose your hair trying.(by pulling it out yourself from frustration)
The fact that you are using python or any other programming language is not relevant in this discussion. It is pure a networking question.
More about NAT/PAT : http://www.webopedia.com/DidYouKnow/Computer_Science/NAT_and_PAT.asp
The major (abstract) idea is simple. You have two node (computers) in a network (this time internet), so you should be able to connect both of them together.
You can establish a tcp connection between them.
Sockets are just fine for your case, all you need is a public IP for each one of them and a free port in each node. You can select your ports from this range.
Python provides a socket module , check it, it is very simple and easy. You may have a look at some examples as well.
However practically speaking, you would need the open these ports in the firewall, and also do some configuration depending on your operating system to allow this kind of communication.
Yes it is possible.
All you need is the hostname or IP address and port number of the computer that you want to connect to. As long as a route can be established to the remote machine, a connection can be made.
Look at the socket module. Here's a simple example:
import socket
s = socket.socket()
s.connect(('123.123.123.123', 10000))
This will attempt to establish a TCP connection to the remote machine with IP address 123.123.123.123 on port 10000. The remote machine will need to have port 10000 open, i.e. a service listening for connection on that port, as well as port 10000 being open in any firewall device.
Instead of the IP address, you can also use a host name:
s.connect(('remote.host.com', 10000))

What's the best way for a Django app to get the current IP address of eth0 [duplicate]

This question already has answers here:
How to get the physical interface IP address from an interface
(3 answers)
Closed 8 years ago.
I've got a Django app that (for obscure reasons) needs to know the IP address of the server it's running on to present it back to the client. I can be pretty sure that the server will have eth0 up and running, so really, I need the address of eth0.
What's the best way to get this? Ideally, this should be enumerated at uwsgi startup, and not necessarily every request. I thought about putting some code in settings.py, but think that might get run/enumerated on every request.
edit I should add that this is a debian linux server, running nginx and running a Django application within uwsgi.
Here is the code that I use to get the public facing ip (on *nix systems):
# Hack to find machine NIC IP
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.4.4", 80))
MACHINE_IP = s.getsockname()[0]
s.close()

Categories

Resources