Skip to content
This repository has been archived by the owner on Sep 30, 2021. It is now read-only.

Add nftables support (instead of iptables) #349

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
* iwconfig (you only need this if 'iw' can not recognize your adapter)
* haveged (optional)

### For 'NATed' or 'None' Internet sharing method
### For 'nat' or 'none' Internet sharing method
* dnsmasq
* iptables


### For 'nft' Internet sharing method
* dnsmasq
* nftables


## Installation
### Generic
git clone https://github.com/oblique/create_ap
Expand Down
2 changes: 1 addition & 1 deletion bash_completion
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ _create_ap() {
# No Options
;;
-m)
opts="nat bridge none"
opts="nat nft bridge none"
;;
--psk)
# No Options
Expand Down
144 changes: 98 additions & 46 deletions create_ap
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
# dnsmasq
# iptables

# dependencies for 'nft' Internet sharing method
# dnsmasq
# nftables

VERSION=0.4.6
PROGNAME="$(basename $0)"

Expand All @@ -37,7 +41,8 @@ usage() {
echo " -n Disable Internet sharing (if you use this, don't pass"
echo " the <interface-with-internet> argument)"
echo " -m <method> Method for Internet sharing."
echo " Use: 'nat' for NAT (default)"
echo " Use: 'nat' for NAT using iptables (default)"
echo " 'nft' for NAT using nftables"
echo " 'bridge' for bridging"
echo " 'none' for no Internet sharing (equivalent to -n)"
echo " --psk Use 64 hex digits pre-shared-key instead of passphrase"
Expand Down Expand Up @@ -715,51 +720,59 @@ _cleanup() {
rm -rf $COMMON_CONFDIR
fi

if [[ "$SHARE_METHOD" != "none" ]]; then
if [[ "$SHARE_METHOD" == "nat" ]]; then
iptables -w -t nat -D POSTROUTING -s ${GATEWAY%.*}.0/24 ! -o ${WIFI_IFACE} -j MASQUERADE || die
iptables -w -D FORWARD -i ${WIFI_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT
iptables -w -D FORWARD -i ${INTERNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
if ! is_bridge_interface $INTERNET_IFACE; then
ip link set dev $BRIDGE_IFACE down
ip link set dev $INTERNET_IFACE down
ip link set dev $INTERNET_IFACE promisc off
ip link set dev $INTERNET_IFACE nomaster
ip link delete $BRIDGE_IFACE type bridge
ip addr flush $INTERNET_IFACE
ip link set dev $INTERNET_IFACE up
dealloc_iface $BRIDGE_IFACE

for x in "${IP_ADDRS[@]}"; do
x="${x/inet/}"
x="${x/secondary/}"
x="${x/dynamic/}"
x=$(echo $x | sed 's/\([0-9]\)sec/\1/g')
x="${x/${INTERNET_IFACE}/}"
ip addr add $x dev $INTERNET_IFACE
done

ip route flush dev $INTERNET_IFACE

for x in "${ROUTE_ADDRS[@]}"; do
[[ -z "$x" ]] && continue
[[ "$x" == default* ]] && continue
ip route add $x dev $INTERNET_IFACE
done

for x in "${ROUTE_ADDRS[@]}"; do
[[ -z "$x" ]] && continue
[[ "$x" != default* ]] && continue
ip route add $x dev $INTERNET_IFACE
done

networkmanager_rm_unmanaged_if_needed $INTERNET_IFACE
fi
if [[ "$SHARE_METHOD" == "nat" ]]; then
iptables -w -t nat -D POSTROUTING -s ${GATEWAY%.*}.0/24 ! -o ${WIFI_IFACE} -j MASQUERADE || die
iptables -w -D FORWARD -i ${WIFI_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT
iptables -w -D FORWARD -i ${INTERNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT
elif [[ "$SHARE_METHOD" == "nft" ]]; then
# Flushing seems to be unnecessary on newer kernels
nft flush chain ip filter create_ap_input
nft flush chain ip filter create_ap_forward
nft flush chain ip nat create_ap_prerouting
nft flush chain ip nat create_ap_postrouting
nft delete chain ip filter create_ap_input
nft delete chain ip filter create_ap_forward
nft delete chain ip nat create_ap_prerouting
nft delete chain ip nat create_ap_postrouting
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
if ! is_bridge_interface $INTERNET_IFACE; then
ip link set dev $BRIDGE_IFACE down
ip link set dev $INTERNET_IFACE down
ip link set dev $INTERNET_IFACE promisc off
ip link set dev $INTERNET_IFACE nomaster
ip link delete $BRIDGE_IFACE type bridge
ip addr flush $INTERNET_IFACE
ip link set dev $INTERNET_IFACE up
dealloc_iface $BRIDGE_IFACE

for x in "${IP_ADDRS[@]}"; do
x="${x/inet/}"
x="${x/secondary/}"
x="${x/dynamic/}"
x=$(echo $x | sed 's/\([0-9]\)sec/\1/g')
x="${x/${INTERNET_IFACE}/}"
ip addr add $x dev $INTERNET_IFACE
done

ip route flush dev $INTERNET_IFACE

for x in "${ROUTE_ADDRS[@]}"; do
[[ -z "$x" ]] && continue
[[ "$x" == default* ]] && continue
ip route add $x dev $INTERNET_IFACE
done

for x in "${ROUTE_ADDRS[@]}"; do
[[ -z "$x" ]] && continue
[[ "$x" != default* ]] && continue
ip route add $x dev $INTERNET_IFACE
done

networkmanager_rm_unmanaged_if_needed $INTERNET_IFACE
fi
fi

if [[ "$SHARE_METHOD" != "bridge" ]]; then
if [[ "$SHARE_METHOD" == "none" || "$SHARE_METHOD" == "nat" ]]; then
if [[ $NO_DNS -eq 0 ]]; then
iptables -w -D INPUT -p tcp -m tcp --dport $DNS_PORT -j ACCEPT
iptables -w -D INPUT -p udp -m udp --dport $DNS_PORT -j ACCEPT
Expand Down Expand Up @@ -1350,7 +1363,7 @@ if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^(8192[cd][ue]|8723a[sue])$
fi
fi

if [[ "$SHARE_METHOD" != "nat" && "$SHARE_METHOD" != "bridge" && "$SHARE_METHOD" != "none" ]]; then
if [[ "$SHARE_METHOD" != "nat" && "$SHARE_METHOD" != "bridge" && "$SHARE_METHOD" != "none" && "$SHARE_METHOD" != "nft" ]]; then
echo "ERROR: Wrong Internet sharing method" >&2
echo
usage >&2
Expand Down Expand Up @@ -1492,7 +1505,7 @@ chmod 444 $CONFDIR/pid
COMMON_CONFDIR=/tmp/create_ap.common.conf
mkdir -p $COMMON_CONFDIR

if [[ "$SHARE_METHOD" == "nat" ]]; then
if [[ "$SHARE_METHOD" == "nat" || "$SHARE_METHOD" == "nft" ]]; then
echo $INTERNET_IFACE > $CONFDIR/nat_internet_iface
cp -n /proc/sys/net/ipv4/conf/$INTERNET_IFACE/forwarding \
$COMMON_CONFDIR/${INTERNET_IFACE}_forwarding
Expand Down Expand Up @@ -1723,6 +1736,20 @@ if [[ "$SHARE_METHOD" != "none" ]]; then
# to enable clients to establish PPTP connections we must
# load nf_nat_pptp module
modprobe nf_nat_pptp > /dev/null 2>&1
elif [[ "$SHARE_METHOD" == "nft" ]]; then
nft table ip filter
nft add chain ip filter create_ap_forward { type filter hook forward priority 0\; }
nft add chain ip filter create_ap_input { type filter hook input priority 0\; }
nft table ip nat
nft add chain ip nat create_ap_prerouting { type nat hook prerouting priority 0\; }
nft add chain ip nat create_ap_postrouting { type nat hook postrouting priority 0\; }

nft add rule ip nat create_ap_postrouting oifname != ${WIFI_IFACE} ip saddr ${GATEWAY%.*}.0/24 masquerade
nft add rule ip filter create_ap_forward iifname ${WIFI_IFACE} ip saddr ${GATEWAY%.*}.0/24 accept
nft add rule ip filter create_ap_forward iifname ${INTERNET_IFACE} ip daddr ${GATEWAY%.*}.0/24 accept
echo 1 > /proc/sys/net/ipv4/conf/$INTERNET_IFACE/forwarding || die
echo 1 > /proc/sys/net/ipv4/ip_forward || die
modprobe nf_nat_pptp > /dev/null 2>&1
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
# disable iptables rules for bridged interfaces
if [[ -e /proc/sys/net/bridge/bridge-nf-call-iptables ]]; then
Expand Down Expand Up @@ -1798,7 +1825,7 @@ else
fi

# start dhcp + dns (optional)
if [[ "$SHARE_METHOD" != "bridge" ]]; then
if [[ "$SHARE_METHOD" == "none" || "$SHARE_METHOD" == "nat" ]]; then
if [[ $NO_DNS -eq 0 ]]; then
DNS_PORT=5353
iptables -w -I INPUT -p tcp -m tcp --dport $DNS_PORT -j ACCEPT || die
Expand All @@ -1820,12 +1847,37 @@ if [[ "$SHARE_METHOD" != "bridge" ]]; then
complain dnsmasq
fi

umask 0033
dnsmasq -C $CONFDIR/dnsmasq.conf -x $CONFDIR/dnsmasq.pid -l $CONFDIR/dnsmasq.leases -p $DNS_PORT || die
umask $SCRIPT_UMASK
fi
elif [[ "$SHARE_METHOD" == "nft" ]]; then
if [[ $NO_DNS -eq 0 ]]; then
DNS_PORT=5353
nft insert rule ip filter create_ap_input tcp dport $DNS_PORT accept || die
nft insert rule ip filter create_ap_input udp dport $DNS_PORT accept || die
nft insert rule ip nat create_ap_prerouting ip saddr ${GATEWAY%.*}.0/24 ip daddr ${GATEWAY} tcp dport 53 redirect to :$DNS_PORT || die
nft insert rule ip nat create_ap_prerouting ip saddr ${GATEWAY%.*}.0/24 ip daddr ${GATEWAY} udp dport 53 redirect to :$DNS_PORT || die
else
DNS_PORT=0
fi

if [[ $NO_DNSMASQ -eq 0 ]]; then
nft insert rule ip filter create_ap_input udp dport 67 accept || die

if which complain > /dev/null 2>&1; then
# openSUSE's apparmor does not allow dnsmasq to read files.
# remove restriction.
complain dnsmasq
fi

umask 0033
dnsmasq -C $CONFDIR/dnsmasq.conf -x $CONFDIR/dnsmasq.pid -l $CONFDIR/dnsmasq.leases -p $DNS_PORT || die
umask $SCRIPT_UMASK
fi
fi


# start access point
echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl"

Expand Down