Compare commits

..

34 Commits

Author SHA1 Message Date
garywill
b4cbcbdbbb is_same_netns: handle if not same pidns 2025-08-16 10:09:08 +08:00
Phani Pavan K
205814a2ea lint remove stray spaces 2025-07-28 14:21:56 +08:00
Phani Pavan Kambhampati
b6fe527472
WiFi 6 Support (#82)
* add options for wifi66

* rebase to 0.7.6 and upgrade version to 0.8.0-unstable0

* fix channel detection

* can_transmit_to_channel: fix 5GHz and 6GHz freq range

* can_transmit_to_channel: limit freq integer part to 4 digits

* enable wmm when wifi 6 is enabled

* lint remove stray spaces

* Revert "lint remove stray spaces"

This reverts commit 8830b95cffc460cb19769630581e029c2be56f05.

---------

Co-authored-by: garywill <garywill@disroot.org>
Co-authored-by: Phani Pavan K <kphanipavan+goose@gmail.com>
2025-07-28 06:16:57 +00:00
garywill
94949ba40b show freq band and channel 2025-07-27 14:12:21 +08:00
garywill
9df05cd81a dependency: crda ,regdb 2025-07-27 13:42:50 +08:00
garywill
01c99f8e4c show config dir at start 2025-07-27 13:03:47 +08:00
garywill
3900871977 add --keep-confdir 2025-07-27 12:55:28 +08:00
garywill
cfeadeb3bd start/exit time in temp config dir 2025-07-27 12:52:59 +08:00
garywill
702c4f28f5 global variable PHY 2025-07-26 10:50:10 +08:00
garywill
3e23e0bd0c refractor freq to channel function (for 2.4G, 5G, 6G) 2025-07-26 10:17:26 +08:00
garywill
fe2348a725 some aa-complain improve 2024-12-18 20:52:53 +08:00
ByteSnipers GmbH
7b374d1ee1 Fix a bug with complian command
added support for aa-complian.
2024-12-18 12:50:44 +00:00
garywill
e7ecf8707d 0.7.6 2024-10-04 12:17:39 +08:00
garywill
fbad56f05c get_pid_by_dbus_name() : fix stderr show 2024-04-20 20:48:05 +08:00
garywill
c376609896 readme text 2024-04-20 20:46:05 +08:00
garywill
a8ae765f03 fix type #73 2024-04-20 20:45:53 +08:00
garywill
d39b438161 0.7.6b 2024-02-25 10:00:00 +08:00
garywill
6aabef278b Detect firewalld and make sure it won't interfere 2024-02-25 10:00:00 +08:00
garywill
8b57dcef1a judge netns 2024-02-25 10:00:00 +08:00
garywill
1def3deb96 improve nm running judgement. use dbus also 2024-02-25 10:00:00 +08:00
garywill
04f473dc64 call disable_unwanted_forward() early 2024-02-25 10:00:00 +08:00
garywill
c1bb2668dd 0.7.5b 2024-02-25 10:00:00 +08:00
garywill
a4e3089e69 disable unwanted forwarding 2024-02-25 10:00:00 +08:00
garywill
8c9e16dd17 explictly ban unwanted forwardings in start_nat() 2024-02-25 10:00:00 +08:00
garywill
40872ebb9e exclude 6 if not enabled 2024-02-25 10:00:00 +08:00
garywill
97b1ef5bd0 merge for start_redsocks() 2024-02-25 10:00:00 +08:00
garywill
9fc74d4bdb add missing local vars 2024-02-25 10:00:00 +08:00
garywill
8759ee43f1 merge for start_catch_dns() 2024-02-25 10:00:00 +08:00
garywill
5f24246e85 merge for allow_dns_port() 2024-02-25 10:00:00 +08:00
garywill
508fefa48f rename GATEWAY to GATEWAY4 2024-02-25 10:00:00 +08:00
garywill
791f6c314b merge for start_ban_lan() 2024-02-25 10:00:00 +08:00
garywill
4db9dcbdb0 merge iptables operation 4 and 6 for start_nat() 2024-02-25 10:00:00 +08:00
garywill
97269da898 use var SUBNET_NET4 , SUBNET_NET6 2024-02-25 10:00:00 +08:00
garywill
9c9b3afde6 use array for iptables custom chain 2024-02-25 10:00:00 +08:00
2 changed files with 548 additions and 361 deletions

View File

@ -25,6 +25,7 @@ Basic features:
- Transparent proxy (redsocks) - Transparent proxy (redsocks)
- Transparent DNS proxy (hijack port 53 packets) - Transparent DNS proxy (hijack port 53 packets)
- Detect NetworkManager and make sure it won't interfere (handle interface (un)managed status) - Detect NetworkManager and make sure it won't interfere (handle interface (un)managed status)
- Detect firewalld and make sure it won't interfere our (by using `trusted` zone)
- You can run many instances, to create many different networks. Has instances managing feature. - You can run many instances, to create many different networks. Has instances managing feature.
**For many other features, see below [CLI usage](#cli-usage-and-other-features)** **For many other features, see below [CLI usage](#cli-usage-and-other-features)**
@ -81,9 +82,9 @@ I'm currently not packaging for any distro. If you do, open a PR and add the lin
- iptables (or nftables with `iptables-nft` translation linked) - iptables (or nftables with `iptables-nft` translation linked)
- WiFi hotspot dependencies - WiFi hotspot dependencies
- hostapd - hostapd
- iw - iw (or iwconfig, when iw can not recognize adapter)
- iwconfig (you only need this if 'iw' can not recognize your adapter)
- haveged (optional) - haveged (optional)
- crda and wireless-regdb (optional)
@ -120,8 +121,6 @@ sudo lnxrouter -i eth1 -o isp5 --no-dns --dhcp-dns 1.1.1.1 -6 --dhcp-dns6 [26
> 1. Stop serving local DNS > 1. Stop serving local DNS
> 2. Tell clients which DNS to use (ISP5's DNS. Or, a safe public DNS, like above example) > 2. Tell clients which DNS to use (ISP5's DNS. Or, a safe public DNS, like above example)
> Also, read *Notice 1*
</details> </details>
### Create LAN without providing Internet ### Create LAN without providing Internet
@ -136,8 +135,6 @@ sudo lnxrouter -n -i eth1
sudo lnxrouter -n --ap wlan0 MyAccessPoint -p MyPassPhrase sudo lnxrouter -n --ap wlan0 MyAccessPoint -p MyPassPhrase
``` ```
> Read _Notice 1_
</details> </details>
### Internet for LXC ### Internet for LXC
@ -312,17 +309,16 @@ Options:
and to provide Internet to and to provide Internet to
(To create WiFi hotspot use '--ap' instead) (To create WiFi hotspot use '--ap' instead)
-o <interface> Specify an inteface to provide Internet from. -o <interface> Specify an inteface to provide Internet from.
(See Notice 1)
(Note using this with default DNS option may leak (Note using this with default DNS option may leak
queries to other interfaces) queries to other interfaces)
-n Do not provide Internet (See Notice 1) -n Do not provide Internet
--ban-priv Disallow clients to access my private network --ban-priv Disallow clients to access my private network
-g <ip> This host's IPv4 address in subnet (mask is /24) -g <ip> This host's IPv4 address in subnet (mask is /24)
(example: '192.168.5.1' or '5' shortly) (example: '192.168.5.1' or '5' shortly)
-6 Enable IPv6 (NAT) -6 Enable IPv6 (NAT)
--no4 Disable IPv4 Internet (not forwarding IPv4) --no4 Disable IPv4 Internet (not forwarding IPv4).
(See Notice 1). Usually used with '-6' Usually used with '-6'
--p6 <prefix> Set IPv6 LAN address prefix (length 64) --p6 <prefix> Set IPv6 LAN address prefix (length 64)
(example: 'fd00:0:0:5::' or '5' shortly) (example: 'fd00:0:0:5::' or '5' shortly)
@ -331,7 +327,7 @@ Options:
--dns <ip>|<port>|<ip:port> --dns <ip>|<port>|<ip:port>
DNS server's upstream DNS. DNS server's upstream DNS.
Use ',' to seperate multiple servers Use ',' to seperate multiple servers
(default: use /etc/resolve.conf) (default: use /etc/resolv.conf)
(Note IPv6 addresses need '[]' around) (Note IPv6 addresses need '[]' around)
--no-dns Do not serve DNS --no-dns Do not serve DNS
--no-dnsmasq Disable dnsmasq server (DHCP, DNS, RA) --no-dnsmasq Disable dnsmasq server (DHCP, DNS, RA)
@ -419,11 +415,10 @@ Options:
For <id> you can use PID or subnet interface name. For <id> you can use PID or subnet interface name.
You can get them with '--list-running' You can get them with '--list-running'
Notice 1: This script assume your host's default policy won't forward Examples:
packets, so the script won't explictly ban forwarding in any lnxrouter -i eth1
mode. In some unexpected case (eg. mistaken configurations) may lnxrouter --ap wlan0 MyAccessPoint -p MyPassPhrase
cause unwanted packets leakage between 2 networks, which you lnxrouter -i eth1 --tp <transparent-proxy> --dns <dns-proxy>
should be aware of if you want isolated network
``` ```
</details> </details>
@ -455,30 +450,9 @@ Visit [**my homepage** 🏡](https://garywill.github.io) to see **more tools and
- 🍃 Also some [unfulfilled enhancements in the Issues](https://github.com/garywill/linux-router/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) - 🍃 Also some [unfulfilled enhancements in the Issues](https://github.com/garywill/linux-router/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)
- 🙋‍♂️ Contributions are not limited to coding. There're [some posts and questions](https://github.com/garywill/linux-router/issues) that need more people to answer - 🙋‍♂️ Contributions are not limited to coding. There're [some posts and questions](https://github.com/garywill/linux-router/issues) that need more people to answer
## Notice
<details>
```
Notice 1: This script assume your host's default policy won't forward
packets, so the script won't explictly ban forwarding in any
mode. In some unexpected case (eg. mistaken configurations) may
cause unwanted packets leakage between 2 networks, which you
should be aware of if you want isolated network
```
</details>
## TODO ## TODO
Sooner is better:
- Detect firewalld and make sure it won't interfere our interface
Future:
- WPA3 - WPA3
- Global IPv6 - Global IPv6
- Explictly ban forwarding if not needed
- Bring bridging method back
## License ## License

547
lnxrouter
View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
VERSION=0.7.3 VERSION=0.8.0-unstable2
PROGNAME="$(basename "$0")" PROGNAME="$(basename "$0")"
export LC_ALL=C export LC_ALL=C
@ -29,17 +29,16 @@ Options:
and to provide Internet to and to provide Internet to
(To create WiFi hotspot use '--ap' instead) (To create WiFi hotspot use '--ap' instead)
-o <interface> Specify an inteface to provide Internet from. -o <interface> Specify an inteface to provide Internet from.
(See Notice 1)
(Note using this with default DNS option may leak (Note using this with default DNS option may leak
queries to other interfaces) queries to other interfaces)
-n Do not provide Internet (See Notice 1) -n Do not provide Internet
--ban-priv Disallow clients to access my private network --ban-priv Disallow clients to access my private network
-g <ip> This host's IPv4 address in subnet (mask is /24) -g <ip> This host's IPv4 address in subnet (mask is /24)
(example: '192.168.5.1' or '5' shortly) (example: '192.168.5.1' or '5' shortly)
-6 Enable IPv6 (NAT) -6 Enable IPv6 (NAT)
--no4 Disable IPv4 Internet (not forwarding IPv4) --no4 Disable IPv4 Internet (not forwarding IPv4).
(See Notice 1). Usually used with '-6' Usually used with '-6'
--p6 <prefix> Set IPv6 LAN address prefix (length 64) --p6 <prefix> Set IPv6 LAN address prefix (length 64)
(example: 'fd00:0:0:5::' or '5' shortly) (example: 'fd00:0:0:5::' or '5' shortly)
@ -48,7 +47,7 @@ Options:
--dns <ip>|<port>|<ip:port> --dns <ip>|<port>|<ip:port>
DNS server's upstream DNS. DNS server's upstream DNS.
Use ',' to seperate multiple servers Use ',' to seperate multiple servers
(default: use /etc/resolve.conf) (default: use /etc/resolv.conf)
(Note IPv6 addresses need '[]' around) (Note IPv6 addresses need '[]' around)
--no-dns Do not serve DNS --no-dns Do not serve DNS
--no-dnsmasq Disable dnsmasq server (DHCP, DNS, RA) --no-dnsmasq Disable dnsmasq server (DHCP, DNS, RA)
@ -125,8 +124,24 @@ Options:
--vht-seg1-ch <channel> Channel index of VHT center frequency for secondary --vht-seg1-ch <channel> Channel index of VHT center frequency for secondary
(second 80MHz) segment. Use with '--vht-ch-width 3' (second 80MHz) segment. Use with '--vht-ch-width 3'
WiFi 6 (802.11ax) configs:
--wifi6 Enable IEEE 802.11ax (HE)
--req-he Require station HE (High Efficiency) mode
--he-ch-width <index> Index of HE channel width:
0 for 20MHz or 40MHz (default)
1 for 80MHz
2 for 160MHz
3 for 80+80MHz (Non-contigous 160MHz)
--he-seg0-ch <channel> Channel index of HE center frequency for primary
segment. Use with '--he-ch-width'
--he-seg1-ch <channel> Channel index of HE center frequency for secondary
(second 80MHz) segment. Use with '--he-ch-width 3'
Instance managing: Instance managing:
--daemon Run in background --daemon Run in background
--keep-confdir Don't delete the temporary config dir after exit
-l, --list-running Show running instances -l, --list-running Show running instances
--lc, --list-clients <id|interface> --lc, --list-clients <id|interface>
List clients of an instance. Or list neighbors of List clients of an instance. Or list neighbors of
@ -136,12 +151,6 @@ Options:
For <id> you can use PID or subnet interface name. For <id> you can use PID or subnet interface name.
You can get them with '--list-running' You can get them with '--list-running'
Notice 1: This script assume your host's default policy won't forward
packets, so the script won't explictly ban forwarding in any
mode. In some unexpected case (eg. mistaken configurations) may
cause unwanted packets leakage between 2 networks, which you
should be aware of if you want isolated network
Examples: Examples:
$PROGNAME -i eth1 $PROGNAME -i eth1
$PROGNAME --ap wlan0 MyAccessPoint -p MyPassPhrase $PROGNAME --ap wlan0 MyAccessPoint -p MyPassPhrase
@ -159,7 +168,7 @@ check_empty_option(){
define_global_variables(){ define_global_variables(){
# user options # user options
GATEWAY= # IPv4 address for this host GATEWAY4= # IPv4 address for this host
PREFIX6= # IPv6 LAN address prefix for this host PREFIX6= # IPv6 LAN address prefix for this host
IID6=1 # IPv6 LAN ID for this host IID6=1 # IPv6 LAN ID for this host
IPV6=0 # enable ipv6 IPV6=0 # enable ipv6
@ -187,6 +196,8 @@ define_global_variables(){
SUBNET_IFACE= # which interface to create network SUBNET_IFACE= # which interface to create network
SHARE_METHOD=nat SHARE_METHOD=nat
OLD_MACADDR= OLD_MACADDR=
SUBNET_NET4=
SUBNET_NET6=
##### wifi hotspot ##### wifi hotspot
@ -202,11 +213,16 @@ define_global_variables(){
REQUIREHT=0 REQUIREHT=0
IEEE80211AC=0 IEEE80211AC=0
REQUIREVHT=0 REQUIREVHT=0
IEEE80211AX=0
REQUIREHE=0
HT_CAPAB='[HT40+]' HT_CAPAB='[HT40+]'
VHT_CAPAB= VHT_CAPAB=
VHTCHANNELWIDTH=0 VHTCHANNELWIDTH=0
VHTSEG0CHINDEX=0 VHTSEG0CHINDEX=0
VHTSEG1CHINDEX=0 VHTSEG1CHINDEX=0
HECHANNELWIDTH=0
HESEG0CHINDEX=0
HESEG1CHINDEX=0
DRIVER=nl80211 DRIVER=nl80211
NO_VIRT=0 # not use virtual interface NO_VIRT=0 # not use virtual interface
COUNTRY= COUNTRY=
@ -218,11 +234,11 @@ define_global_variables(){
QR=0 # show wifi qr QR=0 # show wifi qr
# script variables # script variables
PHY=
VWIFI_IFACE= # virtual wifi interface name, if created VWIFI_IFACE= # virtual wifi interface name, if created
VIRT_NAME= # name to use for virtual interface if --virt-name is used VIRT_NAME= # name to use for virtual interface if --virt-name is used
AP_IFACE= # can be VWIFI_IFACE or WIFI_IFACE AP_IFACE= # can be VWIFI_IFACE or WIFI_IFACE
USE_IWCONFIG=0 # some device can't use iw USE_IWCONFIG=0 # some device can't use iw
####### #######
#-- to deal with info of a running instance. then will exit #-- to deal with info of a running instance. then will exit
@ -232,8 +248,12 @@ define_global_variables(){
# -- variables for running # -- variables for running
CONFDIR= CONFDIR=
NM_RUNNING=0 IP_VERs=
NM_UNM_LIST= # it's called "list" but for now one interface NM_UNM_LIST= # it's called "list" but for now one interface
NM_PID=
FIREWALLD_PID=
TMP_FIREWALLD_ZONE=
KEEP_CONFDIR=
} }
parse_user_options(){ parse_user_options(){
@ -275,7 +295,7 @@ parse_user_options(){
-g) -g)
shift shift
GATEWAY="$1" GATEWAY4="$1"
shift shift
;; ;;
-6) -6)
@ -417,6 +437,14 @@ parse_user_options(){
shift shift
IEEE80211AC=1 IEEE80211AC=1
;; ;;
--wifi6|--ieee80211ax)
shift
IEEE80211AX=1
;;
--req-he|--require-he)
shift
REQUIREHE=1
;;
--req-vht|--require-vht) --req-vht|--require-vht)
shift shift
REQUIREVHT=1 REQUIREVHT=1
@ -446,6 +474,21 @@ parse_user_options(){
VHTSEG1CHINDEX="$1" VHTSEG1CHINDEX="$1"
shift shift
;; ;;
--he-ch-width|--he-channel-width)
shift
HECHANNELWIDTH="$1"
shift
;;
--he-seg0-ch|--he-seg0-channel)
shift
HESEG0CHINDEX="$1"
shift
;;
--he-seg1-ch|--he-seg1-channel)
shift
HESEG1CHINDEX="$1"
shift
;;
--driver) --driver)
shift shift
DRIVER="$1" DRIVER="$1"
@ -510,6 +553,10 @@ parse_user_options(){
LIST_CLIENTS_ID="$1" LIST_CLIENTS_ID="$1"
shift shift
;; ;;
--keep-confdir)
shift
KEEP_CONFDIR=1
;;
*) *)
echo "Invalid parameter: $1" 1>&2 echo "Invalid parameter: $1" 1>&2
@ -585,7 +632,6 @@ get_interface_phy_device() { # only for wifi interface
return 0 return 0
fi fi
done done
echo "Failed to get phy interface" >&2
return 1 return 1
} }
@ -625,15 +671,22 @@ can_be_ap() {
} }
can_transmit_to_channel() { can_transmit_to_channel() {
local IFACE CHANNEL_NUM CHANNEL_INFO local IFACE CHANNEL_NUM CHANNEL_INFO CHANNEL_FREQ_FILTER
IFACE=$1 IFACE=$1
CHANNEL_NUM=$2 CHANNEL_NUM=$2
if [[ $FREQ_BAND == "2.4" ]]; then
CHANNEL_FREQ_FILTER="(24)"
elif [[ $FREQ_BAND -eq 5 ]]; then
CHANNEL_FREQ_FILTER="(5[1-8])"
elif [[ $FREQ_BAND -eq 6 ]]; then
CHANNEL_FREQ_FILTER="((59)|(6[0-9])|(7[0-1]))"
fi
if [[ $USE_IWCONFIG -eq 0 ]]; then if [[ $USE_IWCONFIG -eq 0 ]]; then
CHANNEL_INFO=$(get_adapter_info "${IFACE}" | grep -E " [0-9]+(\.[0-9]+){0,1} MHz \[${CHANNEL_NUM}\]") CHANNEL_INFO=$(get_adapter_info "${IFACE}" | grep -E " ${CHANNEL_FREQ_FILTER}[0-9]{2}(\.[0-9]+){0,1} MHz \[${CHANNEL_NUM}\]")
[[ -z "${CHANNEL_INFO}" ]] && return 1 [[ -z "${CHANNEL_INFO}" ]] && return 1
[[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 1 [[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 2
[[ "${CHANNEL_INFO}" == *disabled* ]] && return 1 [[ "${CHANNEL_INFO}" == *disabled* ]] && return 3
return 0 return 0
else else
CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM}) CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM})
@ -643,20 +696,26 @@ can_transmit_to_channel() {
fi fi
} }
# taken from iw/util.c
ieee80211_frequency_to_channel() { ieee80211_frequency_to_channel() {
local FREQ=$1 local FREQ=$1
if [[ $FREQ -eq 2484 ]]; then
# 2.4G
if [[ $FREQ -ge 2412 && $FREQ -le 2472 ]]; then # 2.4 GHz band: Channels 1-13 (2412~2472 MHz)
echo $(( (FREQ - 2407) / 5 ))
elif [[ $FREQ -eq 2484 ]]; then # 2.4 GHz Channel 14 (2484 MHz, Japan only)
echo 14 echo 14
elif [[ $FREQ -lt 2484 ]]; then
echo $(( ($FREQ - 2407) / 5 )) # 5G
elif [[ $FREQ -ge 4910 && $FREQ -le 4980 ]]; then elif [[ $FREQ -ge 5160 && $FREQ -le 5885 ]]; then # 5 GHz band: Standard Channels 36-165 (5180~5825 MHz) (extra: 32, 169-177)
echo $(( ($FREQ - 4000) / 5 )) echo $(( (FREQ - 5000) / 5 ))
elif [[ $FREQ -le 45000 ]]; then
echo $(( ($FREQ - 5000) / 5 )) # 6G
elif [[ $FREQ -ge 58320 && $FREQ -le 64800 ]]; then elif [[ $FREQ -ge 5955 && $FREQ -le 7115 ]]; then # 6 GHz band: Channels 1-233 (5955~7115 MHz), Wi-Fi 6E/7
echo $(( ($FREQ - 56160) / 2160 )) echo $(( (FREQ - 5950) / 5 ))
else elif [[ $FREQ -eq 5935 ]]; then # 6 GHz band: Special case for 5935 MHz (Channel 2, rare)
echo 2
else # Frequency not in supported Wi-Fi bands (2.4/5/6 GHz)
echo 0 echo 0
fi fi
} }
@ -859,15 +918,43 @@ pid_watchdog() {
} }
#======== #========
get_pid_by_dbus_name() {
local DBUS_NAME="$1"
local pid r
which dbus-send >/dev/null 2>&1 || return 1
pid="$( dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixProcessID string:$DBUS_NAME 2>/dev/null | grep " uint32 " | awk '{print $2}' )"
r=$?
echo "$pid"
return $r
}
is_same_netns() {
local pid2="$1"
local my_netns his_netns
[[ ! -f /proc/$$/ns/net ]] && return 0 # no netns feature. treat as same
my_netns="$(readlink /proc/$$/ns/net)"
his_netns="$(readlink /proc/$pid2/ns/net)"
[[ ! -n "$his_netns" ]] && return 1 # can't find his pid or netns (maybe different pidns), treat as not same
[[ "$my_netns" == "$his_netns" ]] && return 0
return 1
}
#-----------------
# only support NetworkManager >= 0.9.9 # only support NetworkManager >= 0.9.9
is_nm_running() { is_nm_running() {
NM_PID="$(get_pid_by_dbus_name "org.freedesktop.NetworkManager")"
[[ ! -n "$NM_PID" ]] && return 1 # not running
if (which nmcli >/dev/null 2>&1 ) && (nmcli -t -f RUNNING g 2>&1 | grep -E '^running$' >/dev/null 2>&1 ) ; then if (which nmcli >/dev/null 2>&1 ) && (nmcli -t -f RUNNING g 2>&1 | grep -E '^running$' >/dev/null 2>&1 ) ; then
echo 1 if is_same_netns "$NM_PID"; then
else return 0
echo 0 fi
fi fi
NM_PID= # cancel value if treat as not running
return 1 # not running
} }
nm_knows() { nm_knows() {
@ -903,21 +990,38 @@ nm_restore_manage() {
sleep 0.5 sleep 0.5
fi fi
} }
#========= #-------
check_iptables() is_firewalld_running() {
{ FIREWALLD_PID="$(get_pid_by_dbus_name "org.fedoraproject.FirewallD1")"
echo
iptables --version
if which firewall-cmd > /dev/null 2>&1; then [[ ! -n "$FIREWALLD_PID" ]] && return 1 # not running
if [[ "$(firewall-cmd --state 2>&1)" == "running" ]]; then
if (which firewall-cmd >/dev/null 2>&1 ) && [[ "$(firewall-cmd --state 2>&1)" == "running" ]] ; then
if is_same_netns "$FIREWALLD_PID"; then
echo "firewalld is running ($(firewall-cmd --version))" echo "firewalld is running ($(firewall-cmd --version))"
echo -e "\nWARN: We haven't completed the compatibility with firewalld.\nWARN: If you see any trouble, try:\nWARN: 1) 'firewall-cmd --zone=trusted --add-interface=<SUBN_IFACE>'\nWARN: 2) disable firewalld\n" >&2 return 0
# TODO
fi fi
fi fi
FIREWALLD_PID= # cancel value if treat as not running
return 1 # not running
}
firewalld_add_tmpzone() {
# TMP_FIREWALLD_ZONE="lrt${$}${SUBNET_IFACE}"
TMP_FIREWALLD_ZONE="trusted"
# firewall-cmd --new-zone=$TMP_FIREWALLD_ZONE || die "Failed creating temporary firewalld zone"
echo "Adding $SUBNET_IFACE to firewalld '$TMP_FIREWALLD_ZONE' zone"
firewall-cmd --zone=$TMP_FIREWALLD_ZONE --add-interface=$SUBNET_IFACE >/dev/null || die "Failed adding interface to firewalld temporary zone"
}
firewalld_del_tmpzone() {
if [[ -n "$TMP_FIREWALLD_ZONE" ]];then
echo "Removing $SUBNET_IFACE from firewalld '$TMP_FIREWALLD_ZONE' zone"
firewall-cmd --zone=$TMP_FIREWALLD_ZONE --remove-interface=$SUBNET_IFACE >/dev/null
# firewall-cmd --delete-zone=$TMP_FIREWALLD_ZONE
fi
} }
#=========
CUSTOM_CHAINS_4_filter= CUSTOM_CHAINS_4_filter=
CUSTOM_CHAINS_4_nat= CUSTOM_CHAINS_4_nat=
CUSTOM_CHAINS_6_filter= CUSTOM_CHAINS_6_filter=
@ -946,6 +1050,8 @@ iptb()
local FULL="" local FULL=""
local ADD_TO_UNDO=1 local ADD_TO_UNDO=1
local arr_name w
for arr_name in CUSTOM_CHAINS_4_filter CUSTOM_CHAINS_4_nat CUSTOM_CHAINS_6_filter CUSTOM_CHAINS_6_nat for arr_name in CUSTOM_CHAINS_4_filter CUSTOM_CHAINS_4_nat CUSTOM_CHAINS_6_filter CUSTOM_CHAINS_6_nat
do do
local arr_content local arr_content
@ -997,86 +1103,146 @@ iptb()
return $? return $?
} }
disable_unwanted_forwarding() {
for iv in "${IP_VERs[@]}"; do
if [[ "$INTERNET_IFACE" ]]; then
iptb "$iv" n filter I FORWARD \
-i "$SUBNET_IFACE" ! -o "$INTERNET_IFACE" \
-j REJECT || die
iptb "$iv" n filter I FORWARD \
! -i "$INTERNET_IFACE" -o "$SUBNET_IFACE" \
-j REJECT || die
fi
if [[ "$SHARE_METHOD" == 'redsocks' || "$SHARE_METHOD" == 'none' \
|| ( "$iv" -eq "4" && "$NO4" -eq 1 ) ]];then
iptb "$iv" n filter I FORWARD -i "$SUBNET_IFACE" -j REJECT || die
iptb "$iv" n filter I FORWARD -o "$SUBNET_IFACE" -j REJECT || die
fi
done
}
start_nat() { start_nat() {
if [[ $INTERNET_IFACE ]]; then local SUBNET_NET
IPTABLES_NAT_OUT="-o ${INTERNET_IFACE}"
IPTABLES_NAT_IN="-i ${INTERNET_IFACE}" local iv
MASQUERADE_NOTOUT=""
else
MASQUERADE_NOTOUT="! -o ${SUBNET_IFACE}"
fi
echo echo
echo "iptables: NAT " echo "iptables: NAT "
if [[ $NO4 -eq 0 ]]; then
iptb 4 v nat I POSTROUTING -s ${GATEWAY%.*}.0/24 $IPTABLES_NAT_OUT $MASQUERADE_NOTOUT ! -d ${GATEWAY%.*}.0/24 -j MASQUERADE || die
iptb 4 v filter I FORWARD -i ${SUBNET_IFACE} $IPTABLES_NAT_OUT -s ${GATEWAY%.*}.0/24 -j ACCEPT || die
iptb 4 v filter I FORWARD -o ${SUBNET_IFACE} $IPTABLES_NAT_IN -d ${GATEWAY%.*}.0/24 -j ACCEPT || die
fi
iptb 6 v nat I POSTROUTING -s ${PREFIX6}/64 $IPTABLES_NAT_OUT $MASQUERADE_NOTOUT ! -d ${PREFIX6}/64 -j MASQUERADE || die for iv in "${IP_VERs[@]}"; do
iptb 6 v filter I FORWARD -i ${SUBNET_IFACE} $IPTABLES_NAT_OUT -s ${PREFIX6}/64 -j ACCEPT || die [[ "$iv" -eq "4" && ! $NO4 -eq 0 ]] && continue
iptb 6 v filter I FORWARD -o ${SUBNET_IFACE} $IPTABLES_NAT_IN -d ${PREFIX6}/64 -j ACCEPT || die
[[ "$iv" -eq "4" ]] && SUBNET_NET="$SUBNET_NET4"
[[ "$iv" -eq "6" ]] && SUBNET_NET="$SUBNET_NET6"
if [[ -n "$INTERNET_IFACE" ]]; then # only one Internet interface
# masquerade subnet -> internet
iptb "$iv" v nat I POSTROUTING -s "$SUBNET_NET" ! -d "$SUBNET_NET" \
-o "$INTERNET_IFACE" \
-j MASQUERADE || die
# forward subnet -> internet
iptb "$iv" v filter I FORWARD -i "$SUBNET_IFACE" -s "$SUBNET_NET" \
-o $INTERNET_IFACE \
-j ACCEPT || die
# forward any -> subnet
iptb "$iv" v filter I FORWARD -o "$SUBNET_IFACE" -d "$SUBNET_NET" \
-i "$INTERNET_IFACE" \
-j ACCEPT || die
else # any interface can be Internet
# masquerade subnet -> any(!subnet)
iptb "$iv" v nat I POSTROUTING -s "$SUBNET_NET" ! -d "$SUBNET_NET" \
! -o "$SUBNET_IFACE" \
-j MASQUERADE || die
# forward subnet -> any
iptb "$iv" v filter I FORWARD -i "$SUBNET_IFACE" -s "$SUBNET_NET" \
-j ACCEPT || die
# forward any -> subnet
iptb "$iv" v filter I FORWARD -o "$SUBNET_IFACE" -d "$SUBNET_NET" \
-j ACCEPT || die
fi
done
} }
start_ban_lan() { start_ban_lan() {
local arr_nets_to_protect
local ICMP_NAME
local iv s
echo echo
echo "iptables: Disallow clients to access LAN" echo "iptables: Disallow clients to access LAN"
iptb 4 n filter N lrt${$}${SUBNET_IFACE}-BLF || die
# TODO: allow '--dhcp-dns(6)' address port 53, which can be something needed, e.g. a VPN's internal private IP
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 0.0.0.0/8 -j REJECT || die # TODO: use array
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 10.0.0.0/8 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 100.64.0.0/10 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 127.0.0.0/8 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 169.254.0.0/16 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 172.16.0.0/12 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 192.168.0.0/16 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 224.0.0.0/4 -j REJECT || die
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLF -d 255.255.255.255 -j REJECT || die
iptb 4 n filter I FORWARD -i ${SUBNET_IFACE} -j lrt${$}${SUBNET_IFACE}-BLF || die for iv in "${IP_VERs[@]}"; do
# ban forwarding for subnet
iptb "$iv" n filter N lrt${$}${SUBNET_IFACE}-BLF || die
# TODO: allow '--dhcp-dns(6)' address port 53, which can be something needed, e.g. a VPN's internal private IP
if [[ "$iv" -eq "4" ]]; then
arr_nets_to_protect=("0.0.0.0/8" "10.0.0.0/8" "100.64.0.0/10" "127.0.0.0/8" "169.254.0.0/16" "172.16.0.0/12" "192.168.0.0/16" "224.0.0.0/4" "255.255.255.255")
ICMP_NAME="icmp"
elif [[ "$iv" -eq "6" ]]; then
arr_nets_to_protect=("fc00::/7" "fe80::/10" "ff00::/8" "::1" "::/128" "::ffff:0:0/96" "::ffff:0:0:0/96")
ICMP_NAME="icmpv6"
fi
for s in "${arr_nets_to_protect[@]}"; do
iptb "$iv" v filter I lrt${$}${SUBNET_IFACE}-BLF -d "$s" -j REJECT || die
done
iptb "$iv" n filter I FORWARD -i ${SUBNET_IFACE} -j lrt${$}${SUBNET_IFACE}-BLF || die
iptb 4 n filter N lrt${$}${SUBNET_IFACE}-BLI || die # ban input from subnet
iptb 4 v filter I lrt${$}${SUBNET_IFACE}-BLI -i ${SUBNET_IFACE} ! -p icmp -j REJECT || die # ipv6 need icmp to function. TODO: maybe we can block some unneeded icmp to improve security iptb "$iv" n filter N lrt${$}${SUBNET_IFACE}-BLI || die
iptb "$iv" v filter I lrt${$}${SUBNET_IFACE}-BLI -i ${SUBNET_IFACE} ! -p "$ICMP_NAME" -j REJECT || die # ipv6 need icmp to function. TODO: maybe we can block some unneeded icmp to improve security
iptb 4 n filter I INPUT -i ${SUBNET_IFACE} -j lrt${$}${SUBNET_IFACE}-BLI || die iptb "$iv" n filter I INPUT -i ${SUBNET_IFACE} -j lrt${$}${SUBNET_IFACE}-BLI || die
done
iptb 6 n filter N lrt${$}${SUBNET_IFACE}-BLF || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d fc00::/7 -j REJECT || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d fe80::/10 -j REJECT || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d ff00::/8 -j REJECT || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d ::1 -j REJECT || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d ::/128 -j REJECT || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d ::ffff:0:0/96 -j REJECT || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLF -d ::ffff:0:0:0/96 -j REJECT || die
iptb 6 n filter I FORWARD -i ${SUBNET_IFACE} -j lrt${$}${SUBNET_IFACE}-BLF || die
iptb 6 n filter N lrt${$}${SUBNET_IFACE}-BLI || die
iptb 6 v filter I lrt${$}${SUBNET_IFACE}-BLI -i ${SUBNET_IFACE} ! -p icmpv6 -j REJECT || die
iptb 6 n filter I INPUT -i ${SUBNET_IFACE} -j lrt${$}${SUBNET_IFACE}-BLI || die
} }
allow_dns_port() { allow_dns_port() {
local SUBNET_NET
local GATEWAY
local PROTs
local iv pt
echo echo
echo "iptables: allow DNS" echo "iptables: allow DNS"
iptb 4 v filter I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} -p tcp -m tcp --dport 53 -j ACCEPT || die
iptb 4 v filter I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} -p udp -m udp --dport 53 -j ACCEPT || die for iv in "${IP_VERs[@]}"; do
iptb 6 v filter I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -d ${GATEWAY6} -p tcp -m tcp --dport 53 -j ACCEPT || die [[ "$iv" -eq "4" ]] && GATEWAY="$GATEWAY4"
iptb 6 v filter I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -d ${GATEWAY6} -p udp -m udp --dport 53 -j ACCEPT || die [[ "$iv" -eq "6" ]] && GATEWAY="$GATEWAY6"
[[ "$iv" -eq "4" ]] && SUBNET_NET="$SUBNET_NET4"
[[ "$iv" -eq "6" ]] && SUBNET_NET="$SUBNET_NET6"
PROTs=("tcp" "udp")
for pt in "${PROTs[@]}"; do
iptb "$iv" v filter I INPUT -i "$SUBNET_IFACE" -s "$SUBNET_NET" -d "$GATEWAY" -p "$pt" -m "$pt" --dport 53 -j ACCEPT || die
done
done
} }
start_catch_dns() { start_catch_dns() {
local GATEWAY
local PROTs
local iv pt
echo echo
echo "iptables: redirect DNS queries to this host" echo "iptables: redirect DNS queries to this host"
iptb 4 v nat I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY} -p udp -m udp --dport 53 -j REDIRECT --to-ports 53 || die
iptb 4 v nat I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY} -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53 || die
iptb 6 v nat I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY6} -p udp -m udp --dport 53 -j REDIRECT --to-ports 53 || die for iv in "${IP_VERs[@]}"; do
iptb 6 v nat I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY6} -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53 || die [[ "$iv" -eq "4" ]] && GATEWAY="$GATEWAY4"
[[ "$iv" -eq "6" ]] && GATEWAY="$GATEWAY6"
PROTs=("tcp" "udp")
for pt in "${PROTs[@]}"; do
iptb "$iv" v nat I PREROUTING -i "$SUBNET_IFACE" ! -d "$GATEWAY" -p "$pt" -m "$pt" --dport 53 -j REDIRECT --to-ports 53 || die
done
done
} }
@ -1090,44 +1256,41 @@ allow_dhcp() {
# TODO: use 'DNAT' instead of '--to-ports' to support other IP # TODO: use 'DNAT' instead of '--to-ports' to support other IP
start_redsocks() { start_redsocks() {
local SUBNET_NET
local arr_nets_to_ignore
local s iv
echo echo
echo "iptables: transparent proxy non-LAN TCP and UDP(not tested) traffic to port ${TP_PORT}" echo "iptables: transparent proxy non-LAN TCP and UDP(not tested) traffic to port ${TP_PORT}"
if [[ $NO4 -eq 0 ]]; then
iptb 4 n nat N lrt${$}${SUBNET_IFACE}-TP || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 0.0.0.0/8 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 10.0.0.0/8 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 100.64.0.0/10 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 127.0.0.0/8 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 169.254.0.0/16 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 172.16.0.0/12 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 192.168.0.0/16 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 224.0.0.0/4 -j RETURN || die
iptb 4 n nat A lrt${$}${SUBNET_IFACE}-TP -d 255.255.255.255 -j RETURN || die
iptb 4 v nat A lrt${$}${SUBNET_IFACE}-TP -p tcp -j REDIRECT --to-ports ${TP_PORT} || die for iv in "${IP_VERs[@]}"; do
iptb 4 v nat A lrt${$}${SUBNET_IFACE}-TP -p udp -j REDIRECT --to-ports ${TP_PORT} || die [[ "$iv" -eq "4" && ! $NO4 -eq 0 ]] && continue
iptb 4 v nat I PREROUTING -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j lrt${$}${SUBNET_IFACE}-TP || die [[ "$iv" -eq "4" ]] && SUBNET_NET="$SUBNET_NET4"
[[ "$iv" -eq "6" ]] && SUBNET_NET="$SUBNET_NET6"
iptb 4 v filter I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT || die
iptb 4 v filter I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -p udp -m udp --dport ${TP_PORT} -j ACCEPT || die
fi
iptb 6 n nat N lrt${$}${SUBNET_IFACE}-TP || die iptb "$iv" n nat N lrt${$}${SUBNET_IFACE}-TP || die
iptb 6 n nat A lrt${$}${SUBNET_IFACE}-TP -d fc00::/7 -j RETURN || die
iptb 6 n nat A lrt${$}${SUBNET_IFACE}-TP -d fe80::/10 -j RETURN || die
iptb 6 n nat A lrt${$}${SUBNET_IFACE}-TP -d ff00::/8 -j RETURN || die
iptb 6 n nat A lrt${$}${SUBNET_IFACE}-TP -d ::1 -j RETURN || die
iptb 6 n nat A lrt${$}${SUBNET_IFACE}-TP -d :: -j RETURN || die
iptb 6 v nat A lrt${$}${SUBNET_IFACE}-TP -p tcp -j REDIRECT --to-ports ${TP_PORT} || die if [[ "$iv" -eq "4" ]]; then
iptb 6 v nat A lrt${$}${SUBNET_IFACE}-TP -p udp -j REDIRECT --to-ports ${TP_PORT} || die arr_nets_to_ignore=("0.0.0.0/8" "10.0.0.0/8" "100.64.0.0/10" "127.0.0.0/8" "169.254.0.0/16" "172.16.0.0/12" "192.168.0.0/16" "224.0.0.0/4" "255.255.255.255")
elif [[ "$iv" -eq "6" ]];then
arr_nets_to_ignore=("fc00::/7" "fe80::/10" "ff00::/8" "::1" "::")
fi
iptb 6 v nat I PREROUTING -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -j lrt${$}${SUBNET_IFACE}-TP || die for s in "${arr_nets_to_ignore[@]}"; do
iptb "$iv" n nat A lrt${$}${SUBNET_IFACE}-TP -d "$s" -j RETURN || die
done
iptb 6 v filter I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT || die iptb "$iv" v nat A lrt${$}${SUBNET_IFACE}-TP -p tcp -j REDIRECT --to-ports ${TP_PORT} || die
iptb 6 v filter I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -p udp -m udp --dport ${TP_PORT} -j ACCEPT || die iptb "$iv" v nat A lrt${$}${SUBNET_IFACE}-TP -p udp -j REDIRECT --to-ports ${TP_PORT} || die
iptb "$iv" v nat I PREROUTING -i "$SUBNET_IFACE" -s "$SUBNET_NET" -j lrt${$}${SUBNET_IFACE}-TP || die
iptb "$iv" v filter I INPUT -i "$SUBNET_IFACE" -s "$SUBNET_NET" -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT || die
iptb "$iv" v filter I INPUT -i "$SUBNET_IFACE" -s "$SUBNET_NET" -p udp -m udp --dport ${TP_PORT} -j ACCEPT || die
done
} }
#--------------------------------------- #---------------------------------------
@ -1227,10 +1390,12 @@ _cleanup() {
ip addr flush "${SUBNET_IFACE}" ip addr flush "${SUBNET_IFACE}"
rm -rf "$CONFDIR" [[ ! "$KEEP_CONFDIR" -eq 1 ]] && rm -rf "$CONFDIR"
ip link set down dev "${SUBNET_IFACE}" ip link set down dev "${SUBNET_IFACE}"
firewalld_del_tmpzone
if [[ $VWIFI_IFACE ]]; then # the subnet interface (virtual wifi interface) will be removed if [[ $VWIFI_IFACE ]]; then # the subnet interface (virtual wifi interface) will be removed
iw dev "${VWIFI_IFACE}" del iw dev "${VWIFI_IFACE}" del
dealloc_vface_name "$VWIFI_IFACE" dealloc_vface_name "$VWIFI_IFACE"
@ -1261,6 +1426,7 @@ clean_iptables() {
cleanup() { cleanup() {
trap "" SIGINT SIGUSR1 SIGUSR2 EXIT SIGTERM trap "" SIGINT SIGUSR1 SIGUSR2 EXIT SIGTERM
touch "$CONFDIR/exit_$(date +"%Y-%m-%d_%H:%M:%S.%6N")"
echo echo
echo echo
echo "Doing cleanup.. " echo "Doing cleanup.. "
@ -1303,12 +1469,14 @@ init_conf_dirs() {
cd "$TMPDIR" || die "Couldn't change directory to linux-router's temporary path" cd "$TMPDIR" || die "Couldn't change directory to linux-router's temporary path"
CONFDIR="$(mktemp -d $TMPDIR/lnxrouter.${TARGET_IFACE}.conf.XXXXXX)" || die "Instance couldn't make config dir" # config dir for one instance CONFDIR="$(mktemp -d $TMPDIR/lnxrouter.${TARGET_IFACE}.conf.XXXXXX)" || die "Instance couldn't make config dir" # config dir for one instance
chmod 755 "$CONFDIR" echo "Config dir: $CONFDIR"
#echo "Config dir: $CONFDIR" chmod 755 "$CONFDIR" || die "chmod config dir failed"
echo $$ > "$CONFDIR/pid" echo $$ > "$CONFDIR/pid"
touch "$CONFDIR/begin_$(date +"%Y-%m-%d_%H:%M:%S.%6N")"
COMMON_CONFDIR="$TMPDIR/lnxrouter_common.conf" # config dir for all instances COMMON_CONFDIR="$TMPDIR/lnxrouter_common.conf" # config dir for all instances
mkdir -p "$COMMON_CONFDIR" mkdir -p "$COMMON_CONFDIR" || die "Failed creating common config dir"
} }
#== functions to deal with running instances #== functions to deal with running instances
@ -1558,9 +1726,14 @@ daemonizing_check(){
#============================ #============================
check_wifi_settings() { check_wifi_settings() {
PHY="$(get_interface_phy_device "$WIFI_IFACE")"
if [[ -z "$PHY" ]]; then
echo "ERROR: Can't get phy of wifi interface '$WIFI_IFACE' (Did you spell the interface name right?)" >&2
exit 1
fi
if ! ( which iw > /dev/null 2>&1 && iw dev "$WIFI_IFACE" info > /dev/null 2>&1 ); then if ! ( which iw > /dev/null 2>&1 && iw dev "$WIFI_IFACE" info > /dev/null 2>&1 ); then
echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ... (Did you spell the interface name right?)" >&2 echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ..." >&2
USE_IWCONFIG=1 USE_IWCONFIG=1
fi fi
@ -1669,11 +1842,11 @@ decide_target_interface() {
} }
decide_ip_addresses() { decide_ip_addresses() {
if [[ ! -n $GATEWAY ]]; then if [[ ! -n $GATEWAY4 ]]; then
GATEWAY="$(generate_random_ip4)" GATEWAY4="$(generate_random_ip4)"
echo "Use random LAN IPv4 address $GATEWAY" echo "Use random LAN IPv4 address $GATEWAY4"
elif [[ ! "$GATEWAY" =~ "." ]]; then elif [[ ! "$GATEWAY4" =~ "." ]]; then
GATEWAY="192.168.${GATEWAY}.1" GATEWAY4="192.168.${GATEWAY4}.1"
fi fi
if [[ $IPV6 -eq 1 && ! -n $PREFIX6 ]]; then if [[ $IPV6 -eq 1 && ! -n $PREFIX6 ]]; then
@ -1685,6 +1858,10 @@ decide_ip_addresses() {
if [[ $IPV6 -eq 1 ]]; then if [[ $IPV6 -eq 1 ]]; then
GATEWAY6="${PREFIX6}${IID6}" GATEWAY6="${PREFIX6}${IID6}"
fi fi
SUBNET_NET4="${GATEWAY4%.*}.0/24"
[[ $IPV6 -eq 1 ]] && SUBNET_NET6="${PREFIX6}/64"
} }
prepare_wifi_interface() { prepare_wifi_interface() {
@ -1743,6 +1920,8 @@ prepare_wifi_interface() {
CHANNEL=36 CHANNEL=36
fi fi
fi fi
echo "Freq band: $FREQ_BAND GHz Channel: $CHANNEL"
} }
decide_subnet_interface() { decide_subnet_interface() {
@ -1827,6 +2006,16 @@ write_hostapd_conf() {
echo "require_vht=1" >> "$CONFDIR/hostapd.conf" echo "require_vht=1" >> "$CONFDIR/hostapd.conf"
fi fi
if [[ $IEEE80211AX -eq 1 ]]; then
echo "ieee80211ax=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ $REQUIREHE -eq 1 ]]; then
echo "require_he=1" >> "$CONFDIR/hostapd.conf"
fi
if [[ -n "$VHT_CAPAB" ]]; then if [[ -n "$VHT_CAPAB" ]]; then
echo "vht_capab=${VHT_CAPAB}" >> "$CONFDIR/hostapd.conf" echo "vht_capab=${VHT_CAPAB}" >> "$CONFDIR/hostapd.conf"
fi fi
@ -1849,7 +2038,25 @@ write_hostapd_conf() {
EOF EOF
fi fi
if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]]; then if [[ $HECHANNELWIDTH -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
he_oper_chwidth=${HECHANNELWIDTH}
EOF
fi
if [[ $HESEG0CHINDEX -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
he_oper_centr_freq_seg0_idx=${HESEG0CHINDEX}
EOF
fi
if [[ $HESEG1CHINDEX -gt 0 ]]; then
cat <<- EOF >> "$CONFDIR/hostapd.conf"
he_oper_centr_freq_seg1_idx=${HESEG1CHINDEX}
EOF
fi
if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]] || [[ $IEEE80211AX -eq 1 ]]; then
echo "wmm_enabled=1" >> "$CONFDIR/hostapd.conf" echo "wmm_enabled=1" >> "$CONFDIR/hostapd.conf"
fi fi
@ -1874,6 +2081,7 @@ write_hostapd_conf() {
} }
write_dnsmasq_conf() { write_dnsmasq_conf() {
local i
if grep "^nobody:" /etc/group >/dev/null 2>&1 ; then if grep "^nobody:" /etc/group >/dev/null 2>&1 ; then
NOBODY_GROUP="nobody" NOBODY_GROUP="nobody"
else else
@ -1888,12 +2096,12 @@ write_dnsmasq_conf() {
user=nobody user=nobody
group=$NOBODY_GROUP group=$NOBODY_GROUP
bind-dynamic bind-dynamic
listen-address=${GATEWAY} listen-address=${GATEWAY4}
interface=$SUBNET_IFACE interface=$SUBNET_IFACE
except-interface=lo except-interface=lo
no-dhcp-interface=lo no-dhcp-interface=lo
dhcp-range=${GATEWAY%.*}.10,${GATEWAY%.*}.250,255.255.255.0 dhcp-range=${GATEWAY4%.*}.10,${GATEWAY4%.*}.250,255.255.255.0
dhcp-option-force=option:router,${GATEWAY} dhcp-option-force=option:router,${GATEWAY4}
#log-dhcp #log-dhcp
log-facility=$CONFDIR/dnsmasq.log log-facility=$CONFDIR/dnsmasq.log
bogus-priv bogus-priv
@ -1907,7 +2115,7 @@ write_dnsmasq_conf() {
fi fi
if [[ "$DHCP_DNS" != "no" ]]; then if [[ "$DHCP_DNS" != "no" ]]; then
if [[ "$DHCP_DNS" == "gateway" ]]; then if [[ "$DHCP_DNS" == "gateway" ]]; then
dns_offer="$GATEWAY" dns_offer="$GATEWAY4"
else else
dns_offer="$DHCP_DNS" dns_offer="$DHCP_DNS"
fi fi
@ -1983,8 +2191,9 @@ run_wifi_ap_processes() {
echo echo
echo "Starting hostapd" echo "Starting hostapd"
if which complain > /dev/null 2>&1; then if COMPLAIN_CMD="$(command -v aa-complain || command -v complain)"; then
complain hostapd echo "Setting hostapd to AppArmor complain mode..."
"$COMPLAIN_CMD" hostapd
fi fi
# hostapd '-P' works only when use '-B' (run in background) # hostapd '-P' works only when use '-B' (run in background)
@ -2004,10 +2213,9 @@ start_dnsmasq() {
echo echo
echo "Starting dnsmasq" echo "Starting dnsmasq"
if which complain > /dev/null 2>&1; then if COMPLAIN_CMD="$(command -v aa-complain || command -v complain)"; then
# openSUSE's apparmor does not allow dnsmasq to read files. echo "Setting dnsmasq to AppArmor complain mode..."
# remove restriction. "$COMPLAIN_CMD" dnsmasq
complain dnsmasq
fi fi
# Using '-d'(no daemon) dnsmasq will not turn into 'nobody' # Using '-d'(no daemon) dnsmasq will not turn into 'nobody'
@ -2028,10 +2236,8 @@ start_dnsmasq() {
} }
check_rfkill_unblock_wifi() { check_rfkill_unblock_wifi() {
local PHY
if which rfkill > /dev/null 2>&1 ; then if which rfkill > /dev/null 2>&1 ; then
PHY=$(get_interface_phy_device "${SUBNET_IFACE}") rfkill unblock $(rfkill | grep "$PHY" | awk '{print $1}') >/dev/null 2>&1
[[ -n $PHY ]] && rfkill unblock $(rfkill | grep "$PHY" | awk '{print $1}') >/dev/null 2>&1
fi fi
} }
@ -2049,8 +2255,6 @@ ARGS=( "$@" )
parse_user_options "$@" parse_user_options "$@"
# TODO: detect user option conflict # TODO: detect user option conflict
# check if networkManager running
NM_RUNNING="$(is_nm_running)"
TMPDIR="$(decide_tmpdir)" TMPDIR="$(decide_tmpdir)"
@ -2115,7 +2319,7 @@ fi
# judge channel availability after changing country code # judge channel availability after changing country code
if [[ $WIFI_IFACE ]] ; then if [[ $WIFI_IFACE ]] ; then
can_transmit_to_channel "${AP_IFACE}" ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz." can_transmit_to_channel "${AP_IFACE}" ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz. (Tips: 1. Check usable channels: 'iw phy $PHY info'. 2. Check country code then check again. )"
fi fi
[[ $WIFI_IFACE ]] && write_hostapd_conf [[ $WIFI_IFACE ]] && write_hostapd_conf
@ -2123,7 +2327,7 @@ fi
#=================================================== #===================================================
# set interface unmanaged by networkManager # set interface unmanaged by networkManager
if [[ $NM_RUNNING -eq 1 ]] && nm_knows "$TARGET_IFACE"; then # if nm knows target iface, should know subnet iface too. but need to wait until nm finds subnet iface (waiting code is in nm_set_unmanaged() if is_nm_running && nm_knows "$TARGET_IFACE"; then # if nm knows target iface, should know subnet iface too. but need to wait until nm finds subnet iface (waiting code is in nm_set_unmanaged()
nm_set_unmanaged "${SUBNET_IFACE}" # will write NM_UNM_LIST nm_set_unmanaged "${SUBNET_IFACE}" # will write NM_UNM_LIST
fi fi
@ -2140,6 +2344,20 @@ dealwith_mac # setting MAC should be after setting NM unmanaged
[[ $WIFI_IFACE ]] && check_rfkill_unblock_wifi [[ $WIFI_IFACE ]] && check_rfkill_unblock_wifi
echo
iptables --version
echo "Notice: Not showing all operations done to iptables rules"
if [[ "$IPV6" -eq 0 ]]; then
IP_VERs=("4")
else
IP_VERs=("4" "6")
fi
disable_unwanted_forwarding
# bring subnet interface up # bring subnet interface up
ip link set up dev "${SUBNET_IFACE}" || die "Failed bringing ${SUBNET_IFACE} up" ip link set up dev "${SUBNET_IFACE}" || die "Failed bringing ${SUBNET_IFACE} up"
@ -2147,7 +2365,7 @@ ip link set up dev "${SUBNET_IFACE}" || die "Failed bringing ${SUBNET_IFACE} up"
[[ $WIFI_IFACE ]] && run_wifi_ap_processes [[ $WIFI_IFACE ]] && run_wifi_ap_processes
# add ipv4 address to subnet interface # add ipv4 address to subnet interface
ip -4 addr add ${GATEWAY}/24 broadcast ${GATEWAY%.*}.255 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv4 address" ip -4 addr add ${GATEWAY4}/24 broadcast ${GATEWAY4%.*}.255 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv4 address"
set_ipv6_bits set_ipv6_bits
@ -2156,25 +2374,15 @@ if [[ $IPV6 -eq 1 ]] ; then
ip -6 addr add ${GATEWAY6}/64 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv6 address" ip -6 addr add ${GATEWAY6}/64 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv6 address"
fi fi
check_iptables
echo "NOTICE: Not showing all operations done to iptables rules"
[[ "$NO4" -eq 1 ]] && echo -e "\nWARN: Since you're using in this mode (no IPv4 Internet), make sure you've read Notice 1\n" >&2
# enable Internet sharing # enable Internet sharing
if [[ "$SHARE_METHOD" == "none" ]]; then if [[ "$SHARE_METHOD" == "none" ]]; then
echo "No Internet sharing" echo "No Internet sharing"
echo -e "\nWARN: Since you're using in this mode (no Internet share), make sure you've read Notice 1\n" >&2
[[ "$BANLAN" -eq 1 ]] && start_ban_lan [[ "$BANLAN" -eq 1 ]] && start_ban_lan
elif [[ "$SHARE_METHOD" == "nat" ]]; then elif [[ "$SHARE_METHOD" == "nat" ]]; then
[[ "$INTERNET_IFACE" ]] && echo -e "\nWARN: Since you're using in this mode (specify Internet interface), make sure you've read Notice 1\n" >&2
[[ "$INTERNET_IFACE" && "$dnsmasq_NO_DNS" -eq 0 ]] && echo -e "\nWARN: You specified Internet interface but this host is providing local DNS. In some unexpected case (eg. mistaken configurations), queries may leak to other interfaces, which you should be aware of.\n" >&2 [[ "$INTERNET_IFACE" && "$dnsmasq_NO_DNS" -eq 0 ]] && echo -e "\nWARN: You specified Internet interface but this host is providing local DNS. In some unexpected case (eg. mistaken configurations), queries may leak to other interfaces, which you should be aware of.\n" >&2
start_nat start_nat
@ -2214,6 +2422,11 @@ fi
[[ $NO_DNSMASQ -eq 0 ]] && ( allow_dhcp ; start_dnsmasq ) [[ $NO_DNSMASQ -eq 0 ]] && ( allow_dhcp ; start_dnsmasq )
echo ""
is_firewalld_running && firewalld_add_tmpzone
echo echo
echo "== Setting up completed, now linux-router should be working ==" echo "== Setting up completed, now linux-router should be working =="