~fd/ersei.net

36b6345075566a9bc8e2fa0aaa2103e86bde3263 — Ersei Saggi a month ago f841d63
no ip no problemo
1 files changed, 196 insertions(+), 0 deletions(-)

A pages/03.blog/41.no-ip-no-problem/item.en.md
A pages/03.blog/41.no-ip-no-problem/item.en.md => pages/03.blog/41.no-ip-no-problem/item.en.md +196 -0
@@ 0,0 1,196 @@
---
title: 'No IP? No Problem!'
taxonomy:
  category:
    - programming
  tag:
    - linux
    - networking
feed:
  limit: 10
page-toc:
  active: true
highlight: true
publish_date: '2024-10-29 18:40'
date: '2024-10-29 18:40'
staticmath:
  active: false
twig_first: true
visible: false
sitemap: {}
metadata:
  description: 'How to get a free public IPv4 address'
  keywords: linux, networking, public, ip, ipv4, rathole, cloudflare, tunnel
---

This is meant as a tutorial on how to use a VPS to get a public IPv4 address for self-hosting reasons. Often, people want to run a server out of their college dorm that doesn't give them a public IPv4 address, or out of their house from behind [CGNAT](https://en.wikipedia.org/wiki/Carrier-grade_NAT).

It's a simple solution and an excellent alternative to software like [Rathole](https://github.com/rapiz1/rathole) or [Cloudflare Tunnel](https://www.cloudflare.com/products/tunnel) because this solution will properly pass the correct connecting IP addresses through, transparently. If you look at your webserver access logs while using software like Rathole or Cloudflare Tunnel, all the connections are arriving from `127.0.0.1`, and not from the real client address.

===

As a quick introduction, we will create a Wireguard connection between the server without an IP address and a virtual machine in the cloud. Only incoming traffic will go through the cloud VM. All outbound traffic will continue as normal. This means that there will be no latency for normal outbound internet use. The latency will only appear when someone accesses your website.

## Step 1: Acquire a VPS with a Public IPv4 Address

This is not an endorsement, but Oracle Cloud and Google Cloud both have generous free tiers and will give you a static IPv4 address with one virtual machine. Pick a region that is geographically close to where your server is. The specs of the VM are not important—this is extremely lightweight. The most important component is bandwidth, as the bandwidth of this machine will become the bandwidth of the incoming connections. This VPS must be running a modern Linux distribution.

## Step 2: Install Required Software

Verify that you have `nftables` installed on the VPS by running `nft --version`. If it is not installed, do so. Occasionally the `nft` command is kept in `/usr/sbin`, and may not be in the path of a non-root user. Additionally, some distributions may come with alternative firewall software, such as `firewalld` or `ufw`. Please ensure those are uninstalled.

Install Wireguard on both machines. For Debian-based distributions, this will look like `sudo apt install wireguard`, and for Fedora-based distributions `sudo dnf install wireguard-tools`.

## Step 3: Set Up Firewall

On the cloud provider, open the port `51820/UDP` in the cloud firewall. Instructions vary by provider.

Then, on the cloud virtual machine, create the file `/etc/nftables/proxy.nft`:

```
table ip nat {
	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
		meta l4proto tcp tcp dport 80   dnat to 192.168.77.2:80
		meta l4proto tcp tcp dport 443  dnat to 192.168.77.2:443
	}

	chain INPUT {
		type nat hook input priority 100; policy accept;
	}

	chain POSTROUTING {
		type nat hook postrouting priority srcnat; policy accept;
	}

	chain OUTPUT {
		type nat hook output priority -100; policy accept;
	}
}
```

Also create the file `/etc/nftables/main.nft`:

```
# Sample configuration for nftables service.
# Load this by calling 'nft -f /etc/nftables/main.nft'.

# Note about base chain priorities:
# The priority values used in these sample configs are
# offset by 20 in order to avoid ambiguity when firewalld
# is also running which uses an offset of 10. This means
# that packets will traverse firewalld first and if not
# dropped/rejected there will hit the chains defined here.
# Chains created by iptables, ebtables and arptables tools
# do not use an offset, so those chains are traversed first
# in any case.

# drop any existing nftables ruleset
flush ruleset

# a common table for both IPv4 and IPv6
table inet nftables_svc {

	# protocols to allow
	set allowed_protocols {
		type inet_proto
		elements = { icmp, icmpv6 }
	}

	# interfaces to accept any traffic on
	set allowed_interfaces {
		type ifname
		elements = { "lo" }
	}

	# services to allow
	set allowed_tcp_dports {
		type inet_service
		elements = { ssh, http, https, 51820 }
	}

	# services to allow
	set allowed_udp_dports {
		type inet_service
		elements = { 51820 }
	}

	# this chain gathers all accept conditions
	chain allow {
		ct state established,related accept

		meta l4proto @allowed_protocols accept
		iifname @allowed_interfaces accept
		tcp dport @allowed_tcp_dports accept
		udp dport @allowed_udp_dports accept
	}

	# base-chain for traffic to this host
	chain INPUT {
		type filter hook input priority filter + 20
		policy accept

		jump allow
		reject with icmpx type port-unreachable
	}
}

include "/etc/nftables/proxy.nft"
```

This firewall rule will NOT close SSH access. If you have publicly available SSH, that is a bad idea, and you should adjust `allowed_tcp_dports` to not include SSH. This default configuration will only pass through HTTP and HTTPS. Adjust `allowed_tcp_dports` to allow your TCP port, and `allowed_udp_dports` to allow your UDP port. In the first file, use the example HTTP/HTTPS configuration to forward another port. Keep in mind that this port forwarding will take priority! If you have SSH open to the VPS and you try forwarding SSH, you WILL lose SSH access!

## Step 4: Set Up Wireguard

First, set up the Wireguard keys. On the cloud VM, run this command as root:

```
wg genkey | tee privatekey | wg pubkey > publickey
```

Keep these generated files (`privatekey`, `publickey`) in a safe place.

Repeat this generation command on the other machine.

First, create the file `/etc/wireguard/wg0.conf` on the cloud VM:

```
[Interface]
Address = 192.168.77.1/24
ListenPort = 51820
PrivateKey = [FIRST_GENERATED_PRIVATE_KEY]

[Peer]
PublicKey = [THE_PUBLIC_KEY_GENERATED_ON_THE_OTHER_MACHINE]
AllowedIPs = 192.168.77.2/32
PersistentKeepalive = 30
```

Create the file `/etc/wireguard/wg0.conf` on the other machine:

```
[Interface]
PrivateKey = [PRIVATE_KEY_GENERATED_ON_THIS_MACHINE]
Address = 192.168.77.2/32

Table = 123
PreUp = ip rule add from 192.168.77.2 table 123 priority 456
PostDown = ip rule del from 192.168.77.2 table 123 priority 456

[Peer]
PublicKey = [PUBLIC_KEY_GENERATED_ON_THE_OTHER_MACHINE]
Endpoint = [IP_ADDRESS_OF_THE_CLOUD_VM]:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 30
```

Then, reload the firewall rules and start the Wireguard tunnels:

```
sudo systemctl enable --now wg-quick@wg0.service
sudo systemctl restart nftables.service
```

---

That should be all you need to have a public static IPv4 address when self-hosting in an environment where you don't have any such address. If you have any questions, feel free to [contact me](/). Please try fixing your own problem before asking me for help, though. If you do ask me for help, please be as descriptive as possible and tell me the troubleshooting steps you've taken. I'll ignore the cry for help otherwise.