I'm working on something that sends data from one program over UDP to another program at a known IP and port. The program at the known IP and port receives the message from the originating IP but thanks to the NAT the port is obscured (to something like 30129). The program at the known IP and port wants to send an acknowledgement and/or info to the querying program. It can send it back to the original IP and the obscured port #. But how will the querying program know what port to monitor to get it back on? Or, is there a way (this is Python) to say "send this out over port 3200 to known IP (1.2.3.4) on port 7000? That way the known IP/port can respond to port 30129, but it'll get redirected to 3200, which the querying program knows to monitor. Any help appreciated. And no, TCP is not an option.
Okay, I figured it out - the trick is to use the same sock object to receive that you used to send. At least in initial experiments, that seems to do the trick. Thanks for your help.
The simple answer is you don't care what the "real" (ie: pre-natted) port is. Just reply to the nat query and allow the nat to handling delivering the result. If you ABSOLUTELY have to know the source UDP port, include the information in your UDP packet -- but I strongly recommend against this.
Related
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.
Ok, I realize this situation is somewhat unusual, but I need to establish a TCP connection (the 3-way handshake) using only raw sockets (in C, in linux) -- i.e. I need to construct the IP headers and TCP headers myself. I'm writing a server (so I have to first respond to the incoming SYN packet), and for whatever reason I can't seem to get it right. Yes, I realize that a SOCK_STREAM will handle this for me, but for reasons I don't want to go into that isn't an option.
The tutorials I've found online on using raw sockets all describe how to build a SYN flooder, but this is somewhat easier than actually establishing a TCP connection, since you don't have to construct a response based on the original packet. I've gotten the SYN flooder examples working, and I can read the incoming SYN packet just fine from the raw socket, but I'm still having trouble creating a valid SYN/ACK response to an incoming SYN from the client.
So, does anyone know a good tutorial on using raw sockets that goes beyond creating a SYN flooder, or does anyone have some code that could do this (using SOCK_RAW, and not SOCK_STREAM)? I would be very grateful.
MarkR is absolutely right -- the problem is that the kernel is sending reset packets in response to the initial packet because it thinks the port is closed. The kernel is beating me to the response and the connection dies. I was using tcpdump to monitor the connection already -- I should have been more observant and noticed that there were TWO replies one of which was a reset that was screwing things up, as well as the response my program created. D'OH!
The solution that seems to work best is to use an iptables rule, as suggested by MarkR, to block the outbound packets. However, there's an easier way to do it than using the mark option, as suggested. I just match whether the reset TCP flag is set. During the course of a normal connection this is unlikely to be needed, and it doesn't really matter to my application if I block all outbound reset packets from the port being used. This effectively blocks the kernel's unwanted response, but not my own packets. If the port my program is listening on is 9999 then the iptables rule looks like this:
iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP
You want to implement part of a TCP stack in userspace... this is ok, some other apps do this.
One problem you will come across is that the kernel will be sending out (generally negative, unhelpful) replies to incoming packets. This is going to screw up any communication you attempt to initiate.
One way to avoid this is to use an IP address and interface that the kernel does not have its own IP stack using- which is fine but you will need to deal with link-layer stuff (specifically, arp) yourself. That would require a socket lower than IPPROTO_IP, SOCK_RAW - you need a packet socket (I think).
It may also be possible to block the kernel's responses using an iptables rule- but I rather suspect that the rules will apply to your own packets as well somehow, unless you can manage to get them treated differently (perhaps applying a netfilter "mark" to your own packets?)
Read the man pages
socket(7)
ip(7)
packet(7)
Which explain about various options and ioctls which apply to types of sockets.
Of course you'll need a tool like Wireshark to inspect what's going on. You will need several machines to test this, I recommend using vmware (or similar) to reduce the amount of hardware required.
Sorry I can't recommend a specific tutorial.
Good luck.
I realise that this is an old thread, but here's a tutorial that goes beyond the normal SYN flooders: http://www.enderunix.org/docs/en/rawipspoof/
Hope it might be of help to someone.
I can't help you out on any tutorials.
But I can give you some advice on the tools that you could use to assist in debugging.
First off, as bmdhacks has suggested, get yourself a copy of wireshark (or tcpdump - but wireshark is easier to use). Capture a good handshake. Make sure that you save this.
Capture one of your handshakes that fails. Wireshark has quite good packet parsing and error checking, so if there's a straightforward error it will probably tell you.
Next, get yourself a copy of tcpreplay. This should also include a tool called "tcprewrite".
tcprewrite will allow you to split your previously saved capture files into two - one for each side of the handshake.
You can then use tcpreplay to play back one side of the handshake so you have a consistent set of packets to play with.
Then you use wireshark (again) to check your responses.
I don't have a tutorial, but I recently used Wireshark to good effect to debug some raw sockets programming I was doing. If you capture the packets you're sending, wireshark will do a good job of showing you if they're malformed or not. It's useful for comparing to a normal connection too.
There are structures for IP and TCP headers declared in netinet/ip.h & netinet/tcp.h respectively. You may want to look at the other headers in this directory for extra macros & stuff that may be of use.
You send a packet with the SYN flag set and a random sequence number (x). You should receive a SYN+ACK from the other side. This packet will have an acknowledgement number (y) that indicates the next sequence number the other side is expecting to receive as well as another sequence number (z). You send back an ACK packet that has sequence number x+1 and ack number z+1 to complete the connection.
You also need to make sure you calculate appropriate TCP/IP checksums & fill out the remainder of the header for the packets you send. Also, don't forget about things like host & network byte order.
TCP is defined in RFC 793, available here: http://www.faqs.org/rfcs/rfc793.html
Depending on what you're trying to do it may be easier to get existing software to handle the TCP handshaking for you.
One open source IP stack is lwIP (http://savannah.nongnu.org/projects/lwip/) which provides a full tcp/ip stack. It is very possible to get it running in user mode using either SOCK_RAW or pcap.
if you are using raw sockets, if you send using different source mac address to the actual one, linux will ignore the response packet and not send an rst.
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))
I need to transfer data via pyzmq through two computers connected by an ethernet cable. I have already set up a script that runs on the same computer correctly, but I need to find the tcp address of the other computer in order to communicate. They both run Ubuntu 14.04. One of them should be a server processing requests while the other sends requests. How do I transfer data over tcp through ethernet? I simply need a way to find the address.
EDIT: (Clarification) I am running a behavioural study. I have a program called OpenSesame which runs in python and takes python scripts. I need a participant to be able to sit at a computer and be able to ask another person questions (specifically for help in a task). I need a server (using pyzmq preferably) to be connected by ethernet and communicate with that computer. It wrote a script. It works on the same computer, but not over ethernet. I need to find the address
Tcp is a protocol that uses an internet connection to Transfer data, through an IP address and specific port, you have to ensure that those ip directions are in the same range and uses the same port. For example: one pc 192.168.1.50 and another pc 192.168.1.60 in 502 port. The easiest way is using a Modem and set an statical address for each pc.
In the following link, you can find easily in which ip direction is connected your Computer. http://www.howtogeek.com/howto/17012/how-to-find-your-ip-address-in-ubuntu/
Maybe you could periodically send datagram message containing peer's ip address (or some other useful information) to broadcast address, to allow other peers to discover it. And after peer's address is dicovered you can estabish connection via ZeroMQ or other kind... connection. :)
I need some code to get the address of the socket i just created (to filter out packets originating from localhost on a multicast network)
this:
socket.gethostbyname(socket.gethostname())
works on mac but it returns only the localhost IP in linux... is there anyway to get the LAN address
thanks
--edit--
is it possible to get it from the socket settings itself, like, the OS has to select a LAN IP to send on... can i play on getsockopt(... IP_MULTICAST_IF...) i dont know exactly how to use this though...?
--- edit ---
SOLVED!
send_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 0)
putting this on the send socket eliminated packet echos to the host sending them, which eliminates the need for the program to know which IP the OS has selected to send.
yay!
Looks like you're looking for the getsockname method of socket objects.
quick answer - socket.getpeername() (provided that socket is a socket object, not a module)
(playing around in python/ipython/idle/... interactive shell is very helpful)
.. or if I read you question carefully, maybe socket.getsockname() :)