To make our school’s internal resources accessible from the internet, I built a reverse proxy to expose everything behind our firewall to the internet.
Disclaimer: This is an experimental project and everything is protected via Cloudflare Access with Origin Pull to ensure that only me and the people I authorized can access the endpoint.
How to use it?
- Domain Available: Replace
endpoint.domain1 in the domain part of any URL.
- IP Only: Prepend IP address in front of
- If you want to visit
jwzx.cqupt.edu.cn, just type
- Some destination server requires an TLS connection, and
*.secure.endpoint.domainis aimed to do that. Otherwise,
*.endpoint.domainwill initiate a plain HTTP request to the destination.
- Considering there will be many direct IP forwards, and there is no need to acquire a certificate for them. Thus, any domain access like
jwzx.endpoint.domainis provided with a valid wildcard certificate, while IP accesses are not.
- Destinations with unusual port(other than 80 and 443) are not supported and their link will not be overridden.
Under the hood
I used a Raspberry Pi 4 as the gateway benefited by its gigabit ethernet controller.
Of domains ending with
proxy_redirect ~^http://cqupt.edu.cn/(.*) https://endpoint.domain/$1; proxy_redirect ~^http://(.*).cqupt.edu.cn/(.*) https://$1.endpoint.domain/$2; proxy_redirect ~^https://(.*).cqupt.edu.cn/(.*) https://$1.secure.endpoint.domain/$2;
proxy_redirect ~^http://([0-9.]+)/(.*) http://$1.endpoint.domain/$2; proxy_redirect ~^https://([0-9.]+)/(.*) http://$1.secure.endpoint.domain/$2;
Override links on pages.
nginx_substitutions_filter is an enhanced
sub_filter module that allows multiple regexes to replace concurrently.
Check out Substitutions | NGINX to find out more.
subs_filter 'http://cqupt.edu.cn' https://endpoint.domain gir; subs_filter 'http://(.*).cqupt.edu.cn' https://$1.endpoint.domain gir; subs_filter 'https://(.*).cqupt.edu.cn' https://$1.secure.endpoint.domain gir; subs_filter 'http://([0-9.]+)' http://$1.endpoint.domain gir; subs_filter 'https://([0-9.]+)' http://$1.secure.endpoint.domain gir;
There is no need to match exact IPs since I configured a firewall to prevent malicious requests.
Use the following statement to resolve our internal domains from our internal DNS servers.
resolver [ns1.ip] [ns2.ip] valid=3600s;
iptables to filter invalid requests.
# Generated by xtables-save v1.8.3 on Thu Dec 19 03:26:35 2019 *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A OUTPUT -d [network/mask] -p tcp -m owner --uid-owner 33 -j ACCEPT ... -A OUTPUT -d [ns1.ip] -p udp -m owner --uid-owner 33 -j ACCEPT -A OUTPUT -d [ns2.ip] -p udp -m owner --uid-owner 33 -j ACCEPT -A OUTPUT -m owner --uid-owner 33 -j REJECT --reject-with icmp-port-unreachable COMMIT # Completed on Thu Dec 19 03:26:35 2019
endpoint.domaindenotes the domain name of the endpoint just in this article. Remember to replace it in the real world. ↩︎