Skip to content

Instantly share code, notes, and snippets.

@MisakaMikoto-35c5
Last active June 25, 2024 05:42
Show Gist options
  • Save MisakaMikoto-35c5/93d7a32860bbb31b47a05a8c8a0152b8 to your computer and use it in GitHub Desktop.
Save MisakaMikoto-35c5/93d7a32860bbb31b47a05a8c8a0152b8 to your computer and use it in GitHub Desktop.
#!/bin/sh
INTERNAL_IPV6_ADDRESS_RANGE=2001:db8::/64
TARGET_INTERFACE=wan
REAL_INTERFACE=pppoe-$TARGET_INTERFACE
if [ "${INTERFACE}" = "$TARGET_INTERFACE" ]; then
case "${ACTION}" in
ifup|ifupdate)
ip route del default dev $REAL_INTERFACE proto static metric 0
sh -x /usr/sbin/nptv6.sh $REAL_INTERFACE $INTERNAL_IPV6_ADDRESS_RANGE connect
ip -6 ro ad default dev $REAL_INTERFACE proto static metric 512 pref medium
;;
ifdown)
sh -x /usr/sbin/nptv6.sh $REAL_INTERFACE $INTERNAL_IPV6_ADDRESS_RANGE
;;
*) ;;
esac
fi
#!/bin/sh
INTERFACE=$1
PRIVATE_IP_RANGE=$2
OPERATION=$3
function show_help {
echo 'Usage: nptv6.sh Interface LAN_IPv6_Range [Operation]'
echo 'Example: nptv6.sh pppoe-wan fd00::/64'
echo ' nptv6.sh pppoe-wan fd00::/64 connect'
echo 'Operation only have one option: connect.'
echo ' If Operation is connect, this script will find IP'
echo ' address for user define interface. Only the first IP'
echo ' of this interface will be used.'
}
function iptables_setup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
ip6tables -t nat -A POSTROUTING -o $WAN_INTERFACE -j NETMAP \
--to $PUBLIC_IP -s $PRIVATE_IP
ip6tables -t nat -A PREROUTING -i $WAN_INTERFACE -j NETMAP \
-d $PUBLIC_IP --to $PRIVATE_IP
}
function iptables_cleanup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
ip6tables -t nat -D POSTROUTING -o $WAN_INTERFACE -j NETMAP \
--to $PUBLIC_IP -s $PRIVATE_IP
ip6tables -t nat -D PREROUTING -i $WAN_INTERFACE -j NETMAP \
-d $PUBLIC_IP --to $PRIVATE_IP
echo '' > /tmp/nptv6-$INTERFACE
}
function nftables_setup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
nft add rule inet fw4 dstnat ip6 daddr $PUBLIC_IP iif $WAN_INTERFACE \
counter meta nftrace set 1 dnat ip6 prefix to ip6 daddr map { $PUBLIC_IP : $PRIVATE_IP } comment DO_NO_EDIT_Managed_by_nptv6.sh
nft add rule inet fw4 srcnat ip6 saddr $PRIVATE_IP oif $WAN_INTERFACE \
counter meta nftrace set 1 snat ip6 prefix to ip6 saddr map { $PRIVATE_IP : $PUBLIC_IP } comment DO_NO_EDIT_Managed_by_nptv6.sh
}
function nftables_cleanup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
nft delete rule inet fw4 dstnat $(nft -a list table inet fw4 | grep "daddr" | grep DO_NO_EDIT_Managed_by_nptv6.sh | sed -e 's/.* \# //')
nft delete rule inet fw4 srcnat $(nft -a list table inet fw4 | grep "saddr" | grep DO_NO_EDIT_Managed_by_nptv6.sh | sed -e 's/.* \# //')
echo '' > /tmp/nptv6-$INTERFACE
}
if [ ! $INTERFACE ]
then
show_help
exit 1
fi
if [ ! $PRIVATE_IP_RANGE ]
then
show_help
exit 1
fi
which nft
HAS_NFTABLES=$?
touch /tmp/nptv6-$INTERFACE
LAST_IP=`cat /tmp/nptv6-$INTERFACE`
if [ "$LAST_IP" != "" ]
then
echo Remove history iptables rule
if [[ $HAS_NFTABLES -eq 0 ]]; then
nftables_cleanup_nptv6 $PRIVATE_IP_RANGE $LAST_IP $INTERFACE
else
iptables_cleanup_nptv6 $PRIVATE_IP_RANGE $LAST_IP $INTERFACE
fi
fi
if [ $OPERATION == "connect" ]
then
CURRENT_IP=`ip address show dev $INTERFACE to ::/0 scope global | grep inet | sed 's/.*inet6 \([a-f0-9:]*\/\d*\).*/\1/g'`
echo Current IP is: $CURRENT_IP
echo $CURRENT_IP > /tmp/nptv6-$INTERFACE
if [[ $HAS_NFTABLES -eq 0 ]]; then
nftables_setup_nptv6 $PRIVATE_IP_RANGE $CURRENT_IP $INTERFACE
else
iptables_setup_nptv6 $PRIVATE_IP_RANGE $CURRENT_IP $INTERFACE
fi
fi
#!/bin/sh
INTERFACE=$1
PRIVATE_IP_RANGE=$2
OPERATION=$3
function show_help {
echo 'Usage: nptv6.sh Interface LAN_IPv6_Range [Operation]'
echo 'Example: nptv6.sh pppoe-wan fd00::/64'
echo ' nptv6.sh pppoe-wan fd00::/64 connect'
echo 'Operation only have one option: connect.'
echo ' If Operation is connect, this script will find IP'
echo ' address for user define interface. Only the first IP'
echo ' of this interface will be used.'
}
function iptables_setup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
ip6tables -t nat -A POSTROUTING -o $WAN_INTERFACE -j NETMAP \
--to $PUBLIC_IP -s $PRIVATE_IP
ip6tables -t nat -A PREROUTING -i $WAN_INTERFACE -j NETMAP \
-d $PUBLIC_IP --to $PRIVATE_IP
}
function iptables_cleanup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
ip6tables -t nat -D POSTROUTING -o $WAN_INTERFACE -j NETMAP \
--to $PUBLIC_IP -s $PRIVATE_IP
ip6tables -t nat -D PREROUTING -i $WAN_INTERFACE -j NETMAP \
-d $PUBLIC_IP --to $PRIVATE_IP
echo '' > /tmp/nptv6-$INTERFACE
}
function nftables_setup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
nft insert rule inet fw4 dstnat ip6 daddr $PUBLIC_IP iif $WAN_INTERFACE \
counter meta nftrace set 1 dnat ip6 prefix to ip6 daddr map { $PUBLIC_IP : $PRIVATE_IP } comment DO_NO_EDIT_Managed_by_nptv6.sh
nft insert rule inet fw4 srcnat ip6 saddr $PRIVATE_IP oif $WAN_INTERFACE \
counter meta nftrace set 1 snat ip6 prefix to ip6 saddr map { $PRIVATE_IP : $PUBLIC_IP } comment DO_NO_EDIT_Managed_by_nptv6.sh
}
function nftables_cleanup_nptv6 {
PRIVATE_IP=$1
PUBLIC_IP=$2
WAN_INTERFACE=$3
nft delete rule inet fw4 dstnat $(nft -a list table inet fw4 | grep "daddr" | grep DO_NO_EDIT_Managed_by_nptv6.sh | sed -e 's/.* \# //')
nft delete rule inet fw4 srcnat $(nft -a list table inet fw4 | grep "saddr" | grep DO_NO_EDIT_Managed_by_nptv6.sh | sed -e 's/.* \# //')
echo '' > /tmp/nptv6-$INTERFACE
}
function main {
if [ ! $INTERFACE ]
then
show_help
exit 1
fi
if [ ! $PRIVATE_IP_RANGE ]
then
show_help
exit 1
fi
which nft
HAS_NFTABLES=$?
function common_cleanup {
echo Remove history iptables rule
if [[ $HAS_NFTABLES -eq 0 ]]; then
nftables_cleanup_nptv6 $PRIVATE_IP_RANGE $LAST_IP $INTERFACE
else
iptables_cleanup_nptv6 $PRIVATE_IP_RANGE $LAST_IP $INTERFACE
fi
}
touch /tmp/nptv6-$INTERFACE
LAST_IP=`cat /tmp/nptv6-$INTERFACE`
CURRENT_IP=`ip address show dev $INTERFACE to ::/0 scope global | grep inet | sed 's/.*inet6 \([a-f0-9:]*\/\d*\).*/\1/g'`
if [ $OPERATION == "connect" ]
then
nft -a list table inet fw4 | grep DO_NO_EDIT_Managed_by_nptv6.sh | grep $(echo $LAST_IP | sed 's/:\?\(:[a-f0-9]\{1,4\}\)\{1,4\}\/\d*//') > /dev/null
if [[ "$?" -eq 0 ]]; then
echo nochg
return
else
common_cleanup
fi
echo Current IP is: $CURRENT_IP
echo $CURRENT_IP > /tmp/nptv6-$INTERFACE
if [[ $HAS_NFTABLES -eq 0 ]]; then
nftables_setup_nptv6 $PRIVATE_IP_RANGE $CURRENT_IP $INTERFACE
else
iptables_setup_nptv6 $PRIVATE_IP_RANGE $CURRENT_IP $INTERFACE
fi
ip -6 ro ad default from $PRIVATE_IP_RANGE dev $CURRENT_IP metric 512
else
common_cleanup
fi
}
main

OpenWRT-NPTv6-scripts

LICENSE

WTFPL

Note

  • File iptables-nptv6.sh is tested on OpenWRT 19.07 it's use iptables as network filter tool.
  • File nptv6.sh is tested on OpenWRT 23.05, and use nftables as network filter tool. It also keep iptables compatibility but no tested. If have any issue, please comment at below (suggested) or email me.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment