Created
April 23, 2021 15:09
-
-
Save marceloalcocer/880a58a4ac0f51e5de08213c2fc0bd57 to your computer and use it in GitHub Desktop.
1:1 TCP NAT using nftables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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