TURN server behind firewall - how to handle XOR-RELAYED-ADDRESS - networking

I am running a TURN server (http://tools.ietf.org/html/rfc5766) on a server that is behind a firewall. The machine has a public IP address where incoming and outgoing network packets are sent to/from the server's private IP address. Basically, the server cannot bind sockets to the public IP address, only the private IP address. Running ifconfig shows the network device having a private IP address.
When I run the TURN server, I have to bind to the private IP address (since the server doesn't think it is connected to the public Internet). All responses to allocation creations send back the XOR-RELAYED-ADDRESS with the private IP address. Clients receive the XOR-RELAYED-ADDRESS and send data to the server's private IP address, which clearly fails.
There are two options I am considering to overcome this:
Have my client code ignore the IP address of the XOR-RELAYED-ADDRESS and only use the port of XOR-RELAYED-ADDRESS. Clients will send all relayed messages to the TURN server's public IP (since the client already knows this value beforehand) and the XOR-RELAYED-ADDRESS port.
Alter my server to know about its public IP (even though it can't bind sockets to it), and always send back the public IP in XOR-RELAYED-ADDRESS responses.
I feel like the first method breaks the TURN RFC...even though I can't imaging a situation where the TURN server would send back the IP of XOR-RELAYED-ADDRESS as something other than the TURN server's public IP, the RFC says that the XOR-RELAYED-ADDRESS is what clients should be sending data to.
I feel like the second method breaks the RFC less...if that makes sense. Furthermore, this method doesn't force clients to do anything special, whereas the first method needs all clients to abide by the above.
What do you think about this? Has anyone experienced this, and/or have any opinion on which method breaks the RFC less, or if the RFC is even violated by either method?

I have nearly the same exact problem running my STUN server code on Amazon EC2. The origin address and the alternate address returned by the stun server to the client are NAT'd IP addresses.
Some solutions I have thought about:
Just assume clients are pre-configured to know the alternate IP address if they actually want to do the additional NAT type detection tests. This is not a bad assumption to make for STUN. After all, they are expected to know the primary IP address of the stun service.
Modify the server code to be passed it's mapped IP addresses from the command line or config file. This is equivalent to your second method described above. I could have the server self-discover it's own external IP address via a web request (or test another stun server) when it starts up to make this automatic.
Your first proposal - clients are aware of the IP mapping - is perfectly fine assuming you aren't trying to interop with other clients other than your own. But if you think you'll have a need to use someone else's client stack, then this option becomes less desirable. You could do a hybrid approach - invent a new custom attribute for TURN Allocate responses that your client understands to mean, "ignore relay IP, just assume the port is correct". This is OK, but not great.
Your second proposal is more in line with my #2 above. There's one other thing to think about. What happens if your clients are also behind the same firewall as your TURN server? Do you want the internal address or the external? Then again, if both your clients are behind the same firewall, they likely won't need TURN to communicate. The other issue is just the administration overhead of passing the right IP address to the server.
I like your second proposal.
You could consider posting a question to the BEHAVE IETF email discussion group. They are the open committee that drafted the STUN and TURN specs. I think they should be aware that servers in the cloud running behind NATs are becoming increasingly common. They may have some advice. I would be keenly interested in joint authoring this email with you. Or at least reading their response.

Related

Using Client IP address in HttpWebRequest

What I need is quite the same asked here, I don't understand the answer too well, because of my knowledge, so maybe someone could help me.
What I'd like to do is using the connected user's IP address (Client IP) to make the server-side HttpWebRequest, so I would grab the user's IP and make the call with it.
What I'd like to obtain is that every connected user makes HttpWebRequests with their IP.
Is it possible?
If it is, how should I edit that code to do this?
Thanks.
This is impossible. My answer to the other question was about selecting which IP Address (read: network adapter) to use for a request. However, you cannot invent IP Addresses out of thin air, nor use IP Addresses that are not yours (in a physical, attached-to-this-computer sense).
Now, technically, using Raw Sockets, you can spoof another IP Address in your packets. However, the problem with that is that the return traffic will go to the IP Address you specify, not the one you actually have!
So, my advice is to not pursue this line of thought any further, and find another way to do whatever it is that you are trying to do.
You may only make outbound connections from your server using an IP that is assigned to the server. If you tried to use a client's IP, it would fail.
Even if it did not fail, it would be a form of spoofing and would fail pretty qucikly anyway- the handshake that occurs using tcpip would case the remote connection to send an acknowledge packet back to the source ip (in your case, the client ip) which would result in an error.
If you are using UDP, it actually is possible to do this, but that is a different subject.

TURN server XOR-RELAYED-ADDRESS IP different from its own public IP

Suppose I am running a TURN server bound to a public IP (say 100.0.0.1). When the server creates a relay port for a create allocation request, is it ever the case that the server would send back an IP address that is different from whatever it is bound to (100.0.0.1 in this case) in the XOR-RELAYED-ADDRESS attribute? I'm not familiar enough with networking to know all possible scenarios, and the RFC 5766 doesn't really say anything specific (as far as I can tell).
Phrased another way, is the IP address in the XOR-RELAYED-ADDRESS redundant? In all cases I have considered, the client only needs to know the port allocated, and could completely ignore the IP of XOR-RELAYED-ADDRESS. As long as the client knows the relay port, it can always send relay data to the TURN server public IP (it already knows the IP since it had to connect initially...) at the relay port.
Any comments?
If you server is not behind a NAT (on the public internet with a public IP address assigned to it), then the IP address returned in XOR-RELAYED-ADDRESS will be the same. (It will always be the same as the IP address assigned to its NIC).
I assume the reason you are considering ignoring XOR-RELAYED-ADDRESS is related to you other question suggesting the TURN server will actually be behind a NAT/firewall. I think you'll find that the IP address is predictable. But the Firewall/NAT your server sits behind has the possibility of messing up the port allocations. Make sure you understand how the TURN server does port assignments, and that your firewall does port forwarding correctly.
One bit of nomenclature clarification. Your server isn't "bound" to a public or a private IP. Your server socket binds to an interface that has an IP address assigned and associated to it.
Actually, you guys both overlooked a situation when the relay IP address and different from listening IP address, on the TURN server. The TURN Server may be listening on, say, address 1.2.3.4, but it may be allocating the relayed endpoint on two other public addresses - like 2.3.4.5 and 3.4.5.6. The real relayed IP address is returned in XOR-RELAYED-ADDRESS and it may be very different from the listening address.

how to redirect connections to IPs behind the NAT to NATted (public ) IPs at the source?

I have an application that relies on IP addresses for communication (Domain names simply does not work. :(... )
Its function is to connect to its peer on the other machine and send data over after establishing trust. During the "trust establishing" phase they both exchange their IPs for future communication. They both are behind the two different firewalls and are NATted. One is in our NATted office network and other is in the cloud NATted behind their firewall. The applications knows their respective private IPs and exchange that (the 10.x.xxx.xxx range), when they try to connect back to each other (using the private IPs with range 10.x.xxx.xxx) for transferring data they fail. The connection is TCP and the port range is pretty varied.
I am curious if there is anyway I can hard code (for this one time) a rule (at may be firewall level or some place outside my application) that says if there is a connection being initiated for IP address 10.x.xxx.xxx then redirect it to 205.x.xxx.xxx?
Private IP address ranges like 10.x.y.z are, by their very nature, private.
You can't do any meaningful resolution unless each node in between the endpoints has rules in place to translate these.
Translation is tricky, all the main tools you would use cater for static translation (port forwarding, e.g. where a particular port is forwarded to a particular IP). This is one avenue, but it is a hacky one (it requires you to open lots of ports, procedurally update your router and probably have some sort of broker server to maintain mappings).
Alternatively, you could run the isolated networks over a VPN, which would give your endpoints mutual private IPs which you can use to connect to eachother. It would simply be a case of binding to this new address and communicating across the VPN. This would also potentially encrypt your communication over the internet.
Other possibilities are to use NAT/TCP punchthrough techniques which can allow traversal, but these are really a patch to a broken network topology (Read up on IPv6 to see how this can be alleviated).
Alternatively, you could route all the connections over a proxy, but this will complicate matters compared to a VPN.
To answer the question about hardcoding a rule, port forwarding is the solution here. It will obviously depend on your router configuration for the peer accepting the connection, but this client should have the port target port forwarded to the machine. This will obviously not scale very well and is really shifting to a server/client architecture for one connection!
Depending on your hardware, you may be able to forward a range of ports (if a single port cannot be established) and limit the port forwarding to certain incoming connections (the external IPs).
Information on port forwarding can be found at http://portforward.com/
This sounds a lot like what you'd want out of a VPN. Is there anyway that you could set one up? Basically the Site-To-Site VPN between you and the cloud would say 'oh hey, here is an ip located on the remote network, go ahead and connect through the link'. Would this kind of solution work in your case?
Something along these lines: http://i.msdn.microsoft.com/dynimg/IC589512.jpg

How to tamper with source IP address on Windows

We meet a testing scenario which needs to tamper with source IP address of a Http request to simulate clients coming from different countries. Do you know any tool help on this?
Last but not least, our web site is built with ASP.NET.
Thanks.
In a test environment it usually isn't difficult. First read this SO question about virtual network interfaces.
If the server and client are on the same machine, all you have to do is figure out how to get your client software to bind to your virtual interface.
wget for instance has the --bind-address option to specify which local address to bind to. Web browsers are a bit more difficult to do this with; you may need to just run it in a VM.
If your server and client are on the same LAN, you just need to configure your router with some static routes to your client machine. In this case you probably don't need a virtual network interface, just set a static IP for your client machine; as long as the gateway is set up correctly it should be able to send packets to the server, and as long as the route is set up correctly the replies should find their way back to the client.
If the client and server are separated by an internet, it's rather more difficult. One option is to set up a network tunnel endpoint on the server and tunnel it to the client machine, which "knows" that it has the virtual network interface.
As noted in answers to the ServerFault question "Are IP addresses trivial to forge", you cannot easily forge source addresses in a protocol that required two way communication (e.g. TCP). Note that this "two way communication" is required at the packet level. You cannot just say "no problem, I want to send requests and ignore HTTP responses." To establish a TCP session, you need to receive data. Your best bet is to use a proxy server.
I am unsure if the IP standard allows for this, but if you are working in a Lab environment, where you don't need internet connectivity during the test, I can see it working under following circumstances:
Basically, I would set the server's network interface to use netmask 0.0.0.0 and flush the rest of the routing table.
Then you could configure a client machine to take on any IP address as long as you use netmask 0.0.0.0. And two-way communication should be possible.
Server[1.2.3.4/0] <---> Client[x.x.x.x/0]
But please bear with me. I haven't tested this, so I could be wrong :-)
If you have access to your infrastructure, you can add an interface off the router and then place a static route on the router to that network.
Server-----Router----Internet
/
Test_PC----/
Alternatively you can look into PBR (Policy Based Routing) and on the routers you can flag source packets and change the source on the fly, so your server will think they are coming from where you'd like them to come from.
Server-------------Router_with_PBR-------------Internet----- PC
SCR:4.2.2.2 Change SCR:6.6.6.6 to 4.2.2.2 6.6.6.6
But you have to ask yourself why do you want to see when packets come from different countries. Some countries have massive proxy servers that filter access ( "Great Firewall of China"), so the above tests will not prove much.
Your best bet then is using proxy servers or if your looking for a long term solution then setup a server (virtual is great for this) and use RDP for testing. I'm sure you can rent a virtual server somewhere for a month or two.
That's not possible. Because when you forge the ip address, the response is never going to come back, which is required for http.
The best way is to use proxies. See also this question on serverfault.
If you change your source IP address, that means no traffic from your web server will be able to reach back to the client.
You might be able to use some kind of proxy and/or address translation filter to do the remapping while still allowing two-way communication.

Do all web requests contain the requestor's IP?

Am I able to depend on a requestor's IP coming through on all web requests?
I have an asp.net application and I'd like to use the IP to identify unauthenticated visitors. I don't really care if the IP is unique as long as there is something there so that I don't get an empty value.
If not I guess I would have to handle the case where the value is empty.
Or is there a better identifier than IP?
You can get this from Request.ServerVariables["REMOTE_ADDR"].
It doesn't hurt to be defensive. If you're worried about some horrible error condition where this isn't set, check for that case and deal with it accordingly.
There could be many reasons for this value not to be useful. You may only get the address of the last hop, like a load balancer or SSL decoder on the local network. It might be an ISP proxy, or some company NAT firewall.
On that note, some proxies may provide the IP for which they're forwarding traffic in an additional HTTP header, accessible via
Request.ServerVariables["HTTP_X_FORWARDED_FOR"]. You might want to check this first, then fall back to Request.ServerVariables["REMOTE_ADDR"] or Request.UserHostAddress.
It's certainly not a bad idea to log these things for reference/auditing.
I believe that this value is set by your web sever and there is really no way to fake it as your response to there request wouldn't be able to get back to them if they set there IP to something else.
The only thing that you should worry about is proxies. Everyone from a proxy will get the same IP.
You'll always get an IP address, unless your web server is listening on some sort of network that is not an IP network. But the IP address won't necessarily be unique per user.
Well, web request is an http connection, which is a tcp connection and all tcp connections have two endpoints. So, it always exists. But that's about as much as you know about it. It's neither unique nor reliably accurate (with all the proxies and stuff).
Yes, every request must have an IP address, but as stated above, some ISP's use proxies, NAT or gateways which may not give you the individual's computer.
You can easily get this IP (in c#) with:
string IP = Context.Request.ServerVariables["REMOTE_ADDR"].ToString();
or in asp/vbscript with
IP = request.servervariables("REMOTE_ADDR")
IP address is not much use for identifying users. As mentioned already corporate proxies and other private networks can appear as a single IP address.
How are you authenticating users? Typically you would have them log in and then store that state in their session in your app.

Resources