drogonframework / drogonframework/drogon

HostRedirector plugin

Open
#1,783 12 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
14.3k
Forks
1.4k
Avg merge
1d 12h
Merged PRs (30d)
15

Description

# Host Redirector plugin
Creating a host redirector plugin poses some problems, it can be implemented in multiple ways, each with pros and cons.
Before getting into the details, let's establish an environment for testing.

## Subnet 1 (192.168.0.0/24)
Hosted by: Router
Default gateway: 192.168.0.1
DNS server: 192.168.0.1 -> FORWARD -> 8.8.8.8
Devices connected:
1. Drogon server: 192.168.0.2
2. Phone: 192.168.0.3

## Subnet 2 (10.10.10.0/24)
Hosted by: Drogon server (standalone machine)
Default gateway: 10.10.10.1
DNS server: 10.10.10.1 (Custom DNS server running on the machine)
DNS server rules:
1. example.com -> 10.10.10.1
2. anything else -> FORWARD -> 8.8.8.8

Devices connected:
1. Laptop: 10.10.10.2

---

## Scenario - Without Domain Redirector
Now if we connect to the router network using the phone, and navigate to `192.168.0.2`, drogon serves the webpage.
Navigate to `example.com`, it serves [example.com](https://example.com) from the global internet. This is fine, it makes DNS queries to `8.8.8.8`.

Then connect to the drogon server network using the laptop, and navigate to `10.10.10.1`, again, drogon serves the webpage.
Navigate to `example.com`, drogon also serves the webpage. Remember, we have a custom DNS server on that network that resolves DNS queries of `example.com` to `10.10.10.1`.

### Issues
1. The URL does not look good.
2. Different cookies for `example.com` and `10.10.10.1`, even though they are the same thing on the 2nd subnet.

## Scenario - With Domain Redirector
Same as no redirector scenario for the router network.

But things change for the drogon server network. If you go to `10.10.10.1`, drogon will detect you put in an IP address to the server, and will redirect to `example.com`.

Note how it did not redirect when the request came from the router network for `192.168.0.1`, that is because `example.com` within that subnet does not point to `192.168.0.1`, it points somewhere else on the internet. If we had blindly redirected any IP to `example.com`, then drogon will redirect to the global [example.com](https://example.com), away from itself.

---

# Possible solutions

### 1. Dynamic DNS Querying
Using DNS queries to dynamically obtain the IP address of the domain in question, its theoretical config:
```json
"domain": "example.com",
"subdomain": "www"
```
This solution is ideal for safety and ease of use from a server developer or maintainer's point of view.
It handles requests the following way:
```c++
const string &host = ...;
if(!isIP(host))
return nullptr; // Forward as is

const string &ip = host; // Current requested URL
const string &netInterface = req->networkInterface(); // Which network interface this request came from, e.g. wlan0
string ipOfDomain = dnsQuery("example.com", netInterface); // Make a DNS query on that interface
if(ip != ipOfDomain) // ipOfDomain points to somewhere different, possibly global, unsafe to redirect
return nullptr;

return HttpRedirectionResponse("example.com");
```
c-ares may be able to help in this.

Pros:
1. It only redirects safely, and is consistent.
2. Does not require server maintainers to fiddle with IP addresses.

Cons:
1. Implementation of the DNS querying may be difficult if done on the server side.
2. Adds some latency to IP requests, due to drogon making DNS queries to check validity of the domain and IP.

### 2. Hardcoded IP Addresses
Having a list of predefined IP addresses, theoretical config:
```json
"domain": "example.com",
"subdomain": "www",
"ip_addresses": [
"10.10.10.1"
]
```
This is less ideal, as we have to keep track of what IP addresses we are allowed to redirect. Possible implementation:
```c++
const string &host = ...;
if(!isIP(host))
return nullptr; // Forward as is

const string &reqIP = host; // Current requested URL
bool matched = false;
for(const auto &ip : ipAddresses_)
if(ip == reqIP)
{
matched = true;
break;
}

if(!matched)
return nullptr; // Not in our owned IP list

return HttpRedirectionResponse("example.com");
```
Pros:
1. Easier to implement.
2. Faster redirects, and no latency.

Cons:
1. Maintaining a list of IP addresses.

---

## Other ideas

If someone has better solutions or have something on your mind, share it with us to discuss.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.