diff --git a/README.md b/README.md index a56e643..5790bcb 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/bash_completion b/bash_completion index aae0bb2..7053526 100644 --- a/bash_completion +++ b/bash_completion @@ -53,7 +53,7 @@ _create_ap() { # No Options ;; -m) - opts="nat bridge none" + opts="nat nft bridge none" ;; --psk) # No Options diff --git a/create_ap b/create_ap index 8fa6671..e5a0cdf 100755 --- a/create_ap +++ b/create_ap @@ -14,6 +14,10 @@ # dnsmasq # iptables +# dependencies for 'nft' Internet sharing method +# dnsmasq +# nftables + VERSION=0.4.6 PROGNAME="$(basename $0)" @@ -37,7 +41,8 @@ usage() { echo " -n Disable Internet sharing (if you use this, don't pass" echo " the argument)" echo " -m 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" @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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"