Direct Server Return — A Quick Primer

Mahesh Paolini-Subramanya
4 min readMay 7, 2018

--

________________________________________________________________

This is part of a series on Direct Server Return
1.
A Quick Primer
2.
SYN Floods
3.
The Real World
________________________________________________________________

So you’ve got an app that you put up on a server. It’s something important, say, a place where people can get advice from each other on making their own wood-fired pizza ovens.

A) Direct Access
In a very simple scenario, once you set things up, people would access the app by going directly to your server as shown below

If you looked at the actual packets, they would show the source as the client’sIP:Portand the destination as the ServerIP:ServerPort

B) Multiple Servers
You’ve now got a whole bunch-a people using your app, and you need multiple servers to handle the load.

You’re still keeping this simple, and you just tell people to go directly to one of your servers (and if it’s overloaded, pick a different one). If you looked at the actual packets, they would show the source as the client’sIP:Portand the destination as either Server A IP:Server A Portor Server B IP:Server B Portdepending on which server the packet is going to.

C) Router
Now, you don’t really want to make the users deal with picking servers — it’s a pain, and they may just choose to walk away. What you could do is stick a router in front of your servers. Users just send all their requests to the router, instead of having to pick a server.

The question is, where does the router send it’s traffic to? It could randomly send packets to Server A or Server B, which would work as long as nothing the Server is doing is based on anything it did in the past (i.e., it doesn’t need to maintain state). Otherwise, well, chaos, no?

D) Router With State
If the router was smarter, what it could do is remember where the request came from!

In effect, the router does something as follows

  1. The first time it sees a packet from a specific clientIP:Port, it forwards it to a random server (in this case, Server B)
  2. The next time it sees a packet from the same clientIP:Port, it looks up it’s own state (remember, it keeps track of this!) and forwards the packets to the same server

Mind you, it’s actually a bit smarter than this. The actual packet itself is addressed to RouterIP: RouterPort. What the Router does is rewrite the packet so that the packet now looks like it is addressed to Server B IP:Server B Port.

And, of course, on the return path, it takes the packets, and rewrites them so that the client thinks that the response came from RouterIP:RouterPort, and not Server B IP:Server B Port. (otherwise, it might try to communicate directly with Server B, and you certainly don’t want that!)

E) Direct Server Return (DSR)
This is pretty much the same as (D) Router With State above, except that the return traffic doesn’t go back through the router. Instead, Server B itself rewrites each return packet so that that the client thinks that the response came from RouterIP:RouterPort, and not Server B IP:Server B Port.

This basically ensures that the router doesn’t have to handle all the return traffic. It may not seem like that much of an advantage, till you start looking at environments where the return traffic is much much larger than the inbound traffic — e.g., pretty much any streaming service you can think of, like Netflix, YouTube, etc. Without DSR, your outbound traffic is limited by your router capacity, but with DSR, it is the sum of each server’s bandwidth (•).

And there you go, now you know what “Direct Server Return” is!

(•) Yeah, you’re still limited by whatever your upstream provider has set up, but, theoretically, they should be more than happy to sell you more bandwidth. (cough. cough)

(This article also appears on my blog)

--

--