Skip to content

Instantly share code, notes, and snippets.

@marceloalcocer
Created April 23, 2021 15:09
Show Gist options
  • Save marceloalcocer/880a58a4ac0f51e5de08213c2fc0bd57 to your computer and use it in GitHub Desktop.
Save marceloalcocer/880a58a4ac0f51e5de08213c2fc0bd57 to your computer and use it in GitHub Desktop.
1:1 TCP NAT using nftables
#!/usr/bin/env bash
#
# 1:1 TCP NAT using nftables
#
# Implementation of 1:1 network address translation (NAT) between WAN/LAN
# on a Raspberry Pi 4B using nftables. NAT is performed;
#
# * for a single host on the LAN
# * for TCP traffic only
# * to specified ports on the LAN host
# * over ethernet interface on the LAN host
#
# Graphical overview;
#
# --------------------------------------- ------------------------
# | wlan0 | | eth0 | | eth0 | |
# ====| xxx.xxx.x.xxx | RPi | 192.168.0.1 |====| 192.168.0.2 | Host |
# | (WAN, DHCP) | | (LAN, static) | | (LAN, static) | |
# --------------------------------------- ------------------------
#
# Address variables
parse_addr() {
local addr=$( \
echo $(ip --brief -family inet addr show dev ${1}) \
| cut --fields=3 --delimiter=" " \
| cut --fields=1 --delimiter="/" \
)
echo ${addr}
}
IF_RPI_WLAN=wlan0
IF_RPI_ETH=eth0
ADDR_RPI_WLAN="$(parse_addr ${IF_RPI_WLAN})"
ADDR_RPI_ETH=192.168.0.1
ADDR_HOST_ETH=192.168.0.2
PORTS_HOST=5000,8888
# Netfilter variables
TABLE=nat
CHAIN_PRE=prerouting
CHAIN_POST=postrouting
# Routing table
nft add table ip ${TABLE}
# Destination NAT
nft "add chain ip ${TABLE} ${CHAIN_PRE} { \
type nat \
hook prerouting \
priority -100; \
}"
nft "add rule ip ${TABLE} ${CHAIN_PRE} \
meta iif ${IF_RPI_WLAN} `# Received over RPi wlan interface` \
ip daddr ${ADDR_RPI_WLAN} `# to RPi WAN address` \
tcp dport { ${PORTS_HOST} } `# to selected host TCP port` \
dnat ${ADDR_HOST_ETH}" `# => set dest to host LAN address`
# Source NAT
nft "add chain ip ${TABLE} ${CHAIN_POST} { \
type nat \
hook postrouting \
priority 100; \
}"
nft "add rule ip ${TABLE} ${CHAIN_POST} \
meta iif ${IF_RPI_ETH} `# Received over RPi eth interface` \
ip saddr ${ADDR_HOST_ETH} `# from host LAN address` \
meta oif ${IF_RPI_WLAN} `# out over RPi wlan interface` \
snat ${ADDR_RPI_WLAN}" `# => set source to RPi WAN address`
# Enable ip traffic forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment