Linux Static NAT Configuration Using TC
In this Document we will go through the static NAT(also called stateless NAT) configuration using TC Flower.
Required Linux Modules
root@dent-1:/usr/src/linux-5.16.9# lsmod
Module Size Used by
sch_htb 36864 1
sch_ingress 16384 1
act_nat 16384 2
NAT Configuration Example
Topology
The requirement here is to create 1:1 nating for PC1
ip (from 192.168.1.3
to 192.168.122.47
).
Configuration
- Create Egress
Qdisc
on theenp0s4
link, here we used ahtb
type, but another other type can be used. - Create Filter to match packet with
PC1
as source ip, and the action is to do egress nat to192.168.122.47
. - Create Ingress
Qdisc
on theenp0s4
link. - Create Filter to match packet with
192.168.122.47
as destination ip, and the action is to do ingress nat toPC1
ip192.168.1.3
.
- ONM-CLI
- IPROUTE2
- NETCONF
qdiscs-iproute2
qdisc enp0s4 root
qdisc-kind htb
special-qdisc enp0s4 ingress
tc-filters-iproute2
qdisc-filter enp0s4 0:
rule 10
protocol ip
filter flower match src_ip 192.168.1.3
filter flower actions nat direction egress
filter flower actions nat old_ip 192.168.1.3
filter flower actions nat new_ip 192.168.122.47
dev-filter enp0s4 ingress
rule 10
protocol ip
filter flower match dst_ip 192.168.122.47
filter flower actions nat direction ingress
filter flower actions nat old_ip 192.168.122.47
filter flower actions nat new_ip 192.168.1.3
tc qdisc add dev enp0s4 parent root htb
tc filter add dev enp0s4 parent 0: pref 10 protocol ip handle 0x1 flower src_ip 192.168.1.3 action nat egress 192.168.1.3 192.168.122.47
tc qdisc add dev enp0s4 ingress
tc filter add dev enp0s4 ingress pref 10 protocol ip handle 0x1 flower dst_ip 192.168.122.47 action nat ingress 192.168.122.47 192.168.1.3
<config>
<tc-filters>
<qdisc-filter>
<dev>enp0s4</dev>
<parent>0:</parent>
<netns>1</netns>
<rule>
<pref>10</pref>
<flower>
<match>
<src_ip>192.168.1.3</dst_ip>
</match>
<actions>
<nat>
<direction>egress</direction>
<old_ip>192.168.1.3</old_ip>
<new_ip>192.168.122.47</new_ip>
</nat>
</actions>
</flower>
</rule>
</qdisc-filter>
<dev-filter>
<dev>enp0s4</dev>
<direction>ingress</direction>
<netns>1</netns>
<rule>
<pref>10</pref>
<flower>
<match>
<dst_ip>192.168.122.47</dst_ip>
</match>
<actions>
<nat>
<direction>ingress</direction>
<old_ip>192.168.122.47</old_ip>
<new_ip>192.168.1.3</new_ip>
</nat>
</actions>
</flower>
</rule>
</dev-filter>
</tc-filters>
<qdiscs>
<qdisc>
<dev>enp0s4</dev>
<parent>root</parent>
<netns>1</netns>
<qdisc-kind>htb</qdisc-kind>
</qdisc>
<special-qdisc>
<dev>enp0s4</dev>
<qdisc-kind>ingress</qdisc-kind>
<netns>1</netns>
</special-qdisc>
</qdiscs>
</config>
Verify
PC1
can access the internet:
PC1> ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=108 time=87.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=108 time=93.6 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=108 time=81.9 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=108 time=89.3 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=108 time=88.8 ms
- In the capture taken from
dent-1
interfaceenp0s4
we can see that translated ip address: