|
#!/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 |