3 Commits
0.6.0 ... 0.6.2

Author SHA1 Message Date
garywill
c2b21bb391 0.6.2 2021-08-22 09:27:49 +08:00
garywill
e5fc9efe48 support short gateway ip expression
fix dnsmasq pid not get
watchdog zombie judgement
iptables nft and comment judgement
use fifo for dnsmasq log
2021-04-17 12:29:53 +08:00
garywill
1e3c5004c3 some improvements
add '-l'

change MAC addr backking up and restoring judgement to OLD_MACADDR ==
now

filter --lc STATUS==FAILED line

fix iw and iwconfig availability not checked

not use die() before trap
2021-02-22 09:20:41 +08:00
2 changed files with 130 additions and 49 deletions

View File

@@ -4,7 +4,8 @@ Set Linux as router in one command. Able to Provide Internet, or create Wifi hot
It wraps `iptables`, `dnsmasq` etc. stuff. Use in one command, restore in one command or by `control-c` (or even by closing terminal window).
[Buy me a coffee](https://github.com/garywill/receiving/blob/master/receiving_methods.md) :)
[Buy me a coffee](https://github.com/garywill/receiving/blob/master/receiving_methods.md)
## Features
@@ -110,7 +111,9 @@ lxc.network.hwaddr = xx:xx:xx:xx:xx:xx
sudo lnxrouter -i lxcbr5
```
### Transparent proxy with Tor
### Transparent proxy
For example through Tor
```
sudo lnxrouter -i eth1 --tp 9040 --dns 9053 -g 192.168.55.1 --p6 fd00:5:6:7::
@@ -127,7 +130,7 @@ DNSPort [fd00:5:6:7::1]:9053
### Clients-in-sandbox network
To not give our infomation to clients:
To not give our infomation to clients. Clients can still access Internet.
```
sudo lnxrouter -i eth1 \
@@ -232,12 +235,14 @@ Options:
--ban-priv Disallow clients to access my private network
-g <ip> This host's IPv4 address in subnet (mask is /24)
(example: '192.168.5.1' or '5' shortly)
-6 Enable IPv6 (NAT)
--no4 Disable IPv4 Internet (not forwarding IPv4)
(See Notice 1). Usually used with '-6'
--p6 <prefix> Set IPv6 LAN address prefix (length 64)
(example: fd00:1:2:3::) Using this enables '-6'
(example: 'fd00:0:0:5::' or '5' shortly)
Using this enables '-6'
--dns <ip>|<port>|<ip:port>
DNS server's upstream DNS.
@@ -303,10 +308,11 @@ Options:
Instance managing:
--daemon Run in background
--list-running Show running instances
--lc, --list-clients <id>
-l, --list-running Show running instances
--lc, --list-clients <id|interface>
List clients of an instance. Or list neighbors of
any interface, even if it isn't handled by us
an interface, even if it isn't handled by us.
(passive mode)
--stop <id> Stop a running instance
For <id> you can use PID or subnet interface name.
You can get them with '--list-running'
@@ -332,13 +338,13 @@ Options:
- procps or procps-ng
- iproute2
- dnsmasq
- iptables
- iptables (legacy. nft not tested)
- WiFi hotspot dependencies
- hostapd
- iw
- iwconfig (you only need this if 'iw' can not recognize your adapter)
- haveged (optional)
- qrencode (opional)
- qrencode (optional)
## TODO
@@ -351,12 +357,18 @@ Options:
[Buy me a coffee](https://github.com/garywill/receiving/blob/master/receiving_methods.md) , this project took me lots of time!
^\_^o自自o^_^
No? Okay, or just give me a star!
[打赏一个](https://github.com/garywill/receiving/blob/master/receiving_methods.md)
## For developers
**Many thanks to project [create_ap](https://github.com/oblique/create_ap)**.
This script was forked from create\_ap. Now it's quite different from it. (See `history` branch for how I modified create_ap)
There're some TO-DOs listed, at both above and in the code file. We'll appreciate your help.
------------------
More of my projects: https://garywill.github.io

143
lnxrouter
View File

@@ -1,6 +1,7 @@
#!/bin/bash
VERSION=0.6.0
# TODO: showing version (or git commit) on running
VERSION=0.6.2
PROGNAME="$(basename $0)"
export LC_ALL=C
@@ -29,12 +30,14 @@ Options:
--ban-priv Disallow clients to access my private network
-g <ip> This host's IPv4 address in subnet (mask is /24)
(example: '192.168.5.1' or '5' shortly)
-6 Enable IPv6 (NAT)
--no4 Disable IPv4 Internet (not forwarding IPv4)
(See Notice 1). Usually used with '-6'
--p6 <prefix> Set IPv6 LAN address prefix (length 64)
(example: fd00:1:2:3::) Using this enables '-6'
(example: 'fd00:0:0:5::' or '5' shortly)
Using this enables '-6'
--dns <ip>|<port>|<ip:port>
DNS server's upstream DNS.
@@ -100,10 +103,11 @@ Options:
Instance managing:
--daemon Run in background
--list-running Show running instances
--lc, --list-clients <id>
-l, --list-running Show running instances
--lc, --list-clients <id|interface>
List clients of an instance. Or list neighbors of
any interface, even if it isn't handled by us
an interface, even if it isn't handled by us.
(passive mode)
--stop <id> Stop a running instance
For <id> you can use PID or subnet interface name.
You can get them with '--list-running'
@@ -118,7 +122,6 @@ Examples:
$PROGNAME -i eth1
$PROGNAME --ap wlan0 MyAccessPoint
$PROGNAME --ap wlan0 MyAccessPoint -p MyPassPhrase
$PROGNAME -n --ap wlan0 MyAccessPoint -p MyPassPhrase
$PROGNAME -i eth1 --tp <transparent-proxy> --dns <dns-proxy>
EOF
}
@@ -200,6 +203,7 @@ define_global_variables(){
CONFDIR=
NM_RUNNING=0
NM_UNM_LIST= # it's called "list" but for now one interface
XT_COMMENT=1
}
parse_user_options(){
@@ -440,7 +444,7 @@ parse_user_options(){
STOP_ID="$1"
shift
;;
--list-running)
-l|--list-running)
shift
LIST_RUNNING=1
;;
@@ -735,7 +739,7 @@ haveged_watchdog() {
echo "WARN: Low entropy detected. We recommend you to install \`haveged'" 1>&2
show_warn=0
fi
elif ! pidof haveged > /dev/null 2>&1; then
elif ! pidof haveged > /dev/null 2>&1; then # TODO judge zombie ?
echo "Low entropy detected, starting haveged" 1>&2
# boost low-entropy
haveged -w 1024 -p $COMMON_CONFDIR/haveged.pid
@@ -744,7 +748,24 @@ haveged_watchdog() {
sleep 2
done
}
pid_watchdog() {
local PID="$1"
local SLEEP="$2"
local ERR_MSG="$3"
local ST
while true
do
if [[ -e "/proc/$PID" ]]; then
ST="$(cat "/proc/$PID/status" | grep "^State:" | awk '{print $2}')"
if [[ "$ST" != 'Z' ]]; then
sleep $SLEEP
continue
fi
fi
die "$ERR_MSG"
done
}
#========
@@ -791,15 +812,22 @@ nm_restore_manage() {
fi
}
#=========
iptables_()
{
iptables -w $@ -m comment --comment "lnxrouter-$$-$SUBNET_IFACE"
if [[ $XT_COMMENT -eq 1 ]]; then
iptables -w $@ -m comment --comment "lnxrouter-$$-$SUBNET_IFACE"
else
iptables -w $@
fi
return $?
}
ip6tables_()
{
ip6tables -w $@ -m comment --comment "lnxrouter-$$-$SUBNET_IFACE"
if [[ $XT_COMMENT -eq 1 ]]; then
ip6tables -w $@ -m comment --comment "lnxrouter-$$-$SUBNET_IFACE"
else
ip6tables -w $@
fi
return $?
}
@@ -842,7 +870,7 @@ start_ban_lan() {
echo
echo "iptables: Disallow clients to access LAN"
iptables_ -N BANLAN-f-${SUBNET_IFACE} || die
iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 0.0.0.0/8 -j REJECT || die
iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 0.0.0.0/8 -j REJECT || die # TODO: use array
iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 10.0.0.0/8 -j REJECT || die
iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 100.64.0.0/10 -j REJECT || die
iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 127.0.0.0/8 -j REJECT || die
@@ -857,6 +885,7 @@ start_ban_lan() {
iptables_ -N BANLAN-i-${SUBNET_IFACE}
#iptables_ -v -I BANLAN-i-${SUBNET_IFACE} -i ${SUBNET_IFACE} -j REJECT || die
iptables_ -v -I BANLAN-i-${SUBNET_IFACE} -i ${SUBNET_IFACE} ! -p icmp -j REJECT || die
# TODO: ipv6 need icmp to function. maybe we can block some unneeded icmp to improve security
iptables_ -I INPUT -i ${SUBNET_IFACE} -j BANLAN-i-${SUBNET_IFACE} || die
@@ -960,6 +989,7 @@ unallow_dhcp() {
fi
}
# TODO: use 'DNAT' instead of '--to-ports' to support other IP
start_redsocks() {
echo
echo "iptables: transparent proxy non-LAN TCP/UDP traffic to port ${TP_PORT}"
@@ -1026,7 +1056,7 @@ backup_ipv6_bits() {
"/proc/sys/net/ipv6/conf/$SUBNET_IFACE/accept_ra" \
"/proc/sys/net/ipv6/conf/$SUBNET_IFACE/use_tempaddr" \
"/proc/sys/net/ipv6/conf/$SUBNET_IFACE/addr_gen_mode" \
"$CONFDIR/sys_6_conf_iface/" || die "Failed backking up interface ipv6 bits"
"$CONFDIR/sys_6_conf_iface/" || die "Failed backing up interface ipv6 bits"
if [[ "$SHARE_METHOD" == 'redsocks' ]] ; then
cp "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/forwarding" \
@@ -1066,10 +1096,10 @@ backup_interface_status() {
(ip link show ${SUBNET_IFACE} |grep -q "state UP") && SUBNET_IFACE_ORIGINAL_UP_STATUS=1
# save interface old mac
if [[ -n "$NEW_MACADDR" ]]; then
#if [[ -n "$NEW_MACADDR" ]]; then
OLD_MACADDR=$(get_interface_mac $SUBNET_IFACE)
echo "Saved ${SUBNET_IFACE} old MAC address ${OLD_MACADDR} into RAM"
fi
#echo "Saved ${SUBNET_IFACE} old MAC address ${OLD_MACADDR} into RAM"
#fi
backup_ipv6_bits
@@ -1084,9 +1114,9 @@ restore_interface_status() {
restore_ipv6_bits
if [[ -n "$OLD_MACADDR" ]] ; then
if [[ -n "$OLD_MACADDR" && "$(get_interface_mac $SUBNET_IFACE)" != "$OLD_MACADDR" ]] ; then
echo "Restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR} ..."
set_interface_mac ${SUBNET_IFACE} ${OLD_MACADDR} && echo "Successfully restored ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR}"
set_interface_mac ${SUBNET_IFACE} ${OLD_MACADDR} || echo "Failed restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR}" >&2
fi
nm_restore_manage
@@ -1180,6 +1210,7 @@ cleanup() {
#kill -9 -$pgid
}
# NOTE function die() is designed not to be used before init_trap() executed
die() { # SIGUSR2
echo "Error occured"
[[ -n "$1" ]] && echo -e "\nERROR: $1\n" >&2
@@ -1204,7 +1235,7 @@ init_conf_dirs() {
chmod 755 "$TMPDIR" 2>/dev/null
cd "$TMPDIR" || die "Couldn't change directory to linux-router's temporary path"
CONFDIR="$(mktemp -d $TMPDIR/lnxrouter.${TARGET_IFACE}.conf.XXX)" || 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 $$ > "$CONFDIR/pid"
@@ -1267,18 +1298,19 @@ print_clients_from_leases() { # MAC|IP|HOST|lease
FILEC="$(cat "$LEASE_FILE" | grep -v -E "^duid\b" | sed -r '/^\s*$/d' )"
# TODO: duid is somewhat related to ipv6. I don't know about it. Not sure excluding it miss some info or not
echo "$FILEC" | while read line
do
#echo aa$line
LEASEstamp="$(echo "$line" | awk '{print $1}')"
MAC="$(echo "$line" | awk '{print $2}')"
IP="$(echo "$line" | awk '{print $3}' | sed 's/\[//g' | sed 's/\]//g')"
HOST="$(echo "$line" | awk '{print $4}' | sed 's/*/?/g')"
HOST="$(echo "$line" | awk '{print $4}' | sed 's/*/?/g' | sed 's/|/_/g' | sed 's/ /_/g' )"
if [[ -n "$MAC" ]]; then
LEASEstr="$(date -d @${LEASEstamp} +%m-%d_%X)"
echo "$MAC|$IP|$HOST|$LEASEstr"
echo "$MAC|$IP|$HOST|lease_$LEASEstr"
fi
done
@@ -1303,7 +1335,7 @@ print_interface_neighbors_via_iproute() { # MAC|IP|_|STATUS
MAC="?"
STATUS="$(echo $line | awk -F'|' '$1="";$2="";$3="";$4="";{print}' | awk '{$1=$1;print}' | sed 's/ /,/g')"
fi
if [[ -n "$IP" ]]; then
if [[ -n "$IP" && ( "$MAC" != "?" || "$STATUS" != "FAILED" ) ]]; then
echo "$MAC|$IP|?|$STATUS"
fi
done
@@ -1315,12 +1347,12 @@ print_interface_neighbors_via_iw() { # MAC|_|_|signal
do
if [[ -n "$MAC" ]]; then
SIGNAL="$(iw dev $IFACE station get $MAC | grep "signal:" | awk '{print $2}')"
echo "${MAC}|?|?|${SIGNAL} dBm"
echo "${MAC}|?|?|${SIGNAL}_dBm"
fi
done
}
list_clients() {
list_clients() { # passive mode. (use 'arp-scan' or 'netdiscover' if want active mode)
local IFACE pid
local CONFDIR
@@ -1336,7 +1368,7 @@ list_clients() {
else # non-number given
IFACE="$1"
if ( ! is_interface $IFACE ) ; then
echo "'$IFACE' is not an interface" >&2
echo "'$IFACE' is not an interface or PID" >&2
exit 1
fi
pid=$(get_pid_from_subn_iface "$IFACE")
@@ -1459,6 +1491,19 @@ daemonizing_check(){
#============================
check_wifi_settings() {
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') ..." >&2
USE_IWCONFIG=1
fi
if [[ $USE_IWCONFIG -eq 1 ]]; then
if ! (which iwconfig > /dev/null 2>&1 && iwconfig $WIFI_IFACE > /dev/null 2>&1); then
echo "ERROR: Can't use 'iwconfig' to operate interfce '$WIFI_IFACE'" >&2
exit 1
fi
fi
if [[ $FREQ_BAND != 2.4 && $FREQ_BAND != 5 ]]; then
echo "ERROR: Invalid frequency band" >&2
exit 1
@@ -1547,8 +1592,8 @@ decide_target_interface() {
elif [[ "$WIFI_IFACE" ]]; then
echo "$WIFI_IFACE"
else
die "No target interface specified"
exit 1
echo "No target interface specified" >&2
return 1
fi
}
@@ -1556,11 +1601,15 @@ decide_ip_addresses() {
if [[ ! -n $GATEWAY ]]; then
GATEWAY="$(generate_random_ip4)"
echo "Use random LAN IPv4 address $GATEWAY"
elif [[ ! "$GATEWAY" =~ "." ]]; then
GATEWAY="192.168.${GATEWAY}.1"
fi
if [[ $IPV6 -eq 1 && ! -n $PREFIX6 ]]; then
PREFIX6="$(generate_random_lan_ip6_prefix)"
echo "Use random LAN IPv6 address ${PREFIX6}${IID6}"
elif [[ ! "$PREFIX6" =~ ":" ]]; then
PREFIX6="fd00:0:0:${PREFIX6}::"
fi
if [[ $IPV6 -eq 1 ]]; then
GATEWAY6="${PREFIX6}${IID6}"
@@ -1595,8 +1644,9 @@ prepare_wifi_interface() {
VWIFI_IFACE=$(alloc_new_vface_name)
if iw dev ${WIFI_IFACE} interface add ${VWIFI_IFACE} type __ap; then
# Successfully created virtual wifi interface
sleep 2 # wait for virtual interface MAC may change by system (but could be changed back by other programs)
echo "${VWIFI_IFACE} created)"
# if NM running, it will give the new virtual interface a random MAC. MAC will go back after setting NM unmanaged
sleep 2
echo "${VWIFI_IFACE} created"
else
VWIFI_IFACE=
die "Failed creating virtual WiFi interface. Maybe your WiFi adapter does not fully support virtual interfaces. Try again with '--no-virt'"
@@ -1712,6 +1762,11 @@ write_dnsmasq_conf() {
else
NOBODY_GROUP="nogroup"
fi
mkfifo "$CONFDIR/dnsmasq.log" || die "Failed creating pipe file for dnsmasq"
chown nobody "$CONFDIR/dnsmasq.log" || die "Failed changing dnsmasq log file owner"
cat "$CONFDIR/dnsmasq.log" &
cat <<- EOF > "$CONFDIR/dnsmasq.conf"
user=nobody
group=$NOBODY_GROUP
@@ -1723,7 +1778,7 @@ write_dnsmasq_conf() {
dhcp-range=${GATEWAY%.*}.10,${GATEWAY%.*}.250,255.255.255.0
dhcp-option-force=option:router,${GATEWAY}
#log-dhcp
log-facility=/dev/stdout
log-facility=$CONFDIR/dnsmasq.log
bogus-priv
domain-needed
EOF
@@ -1814,8 +1869,7 @@ run_wifi_ap_processes() {
# sleep 1
#done
#echo -n "hostapd PID: " ; cat $CONFDIR/hostapd.pid
( while [ -e /proc/$HOSTAPD_PID ]; do sleep 10; done ; die "hostapd exited" ) &
pid_watchdog $HOSTAPD_PID 10 "hostapd failed" &
sleep 3
}
@@ -1838,9 +1892,10 @@ start_dnsmasq() {
i=$((i + 1))
if [[ $i -gt 10 ]]; then die "Couldn't get dnsmasq PID" ; fi
done
echo -n "dnsmasq PID: " ; cat "$CONFDIR/dnsmasq.pid"
DNSMASQ_PID="$(cat "$CONFDIR/dnsmasq.pid" )"
echo "dnsmasq PID: $DNSMASQ_PID"
######(wait $DNSMASQ_PID ; die "dnsmasq failed") & # wait can't deal with non-child
( while [ -e "/proc/$DNSMASQ_PID" ]; do sleep 10; done ; die "dnsmasq exited" ) &
pid_watchdog $DNSMASQ_PID 9 "dnsmasq failed" &
sleep 2
}
@@ -1890,8 +1945,9 @@ daemonizing_check
## ========================================================
echo "PID: $$"
TARGET_IFACE="$(decide_target_interface)" # judge wired (-i CONN_IFACE) or wireless hotspot (--ap $WIFI_IFACE)
echo "Target interface is ${TARGET_IFACE}"
TARGET_IFACE="$(decide_target_interface)" || exit 1 # judge wired (-i CONN_IFACE) or wireless hotspot (--ap $WIFI_IFACE)
echo "Target interface is ${TARGET_IFACE} ($(get_interface_mac $TARGET_IFACE))"
# TODO: show interface type, device model and pci/usb id (hwdata pci.ids), current driver
if [[ "$MAC_USE_RANDOM" -eq 1 ]] ; then
NEW_MACADDR="$(generate_random_mac)"
@@ -1907,6 +1963,7 @@ decide_ip_addresses # ip 4 & 6 lan addresses
#==== begin to do some change on config files and system===
init_trap
# NOTE function die() is designed not to be used before init_trap() executed
init_conf_dirs # CONFDIR , COMMON_CONFDIR . make dir
@@ -1947,7 +2004,7 @@ ip link set down dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} down
# flush old IPs of subnet interface
ip addr flush ${SUBNET_IFACE} || die "Failed flush ${SUBNET_IFACE} IP"
dealwith_mac
dealwith_mac # setting MAC should be after setting NM unmanaged
[[ $WIFI_IFACE ]] && check_rfkill_unblock_wifi
@@ -1967,6 +2024,18 @@ if [[ $IPV6 -eq 1 ]] ; then
ip -6 addr add ${GATEWAY6}/64 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv6 address"
fi
function check_iptables() {
if iptables --version | grep "nf_tables" >/dev/null 2>&1 ; then
echo -e "\nWARN: Your system is using nftables. This script is tested with iptables legacy only. If you encounter problems, visit following URL for infomation:\n https://github.com/oblique/create_ap/issues/373\n https://github.com/oblique/create_ap/issues/433\n https://github.com/garywill/linux-router/issues/18\n" >&2
fi
if ! lsmod | grep -E "\bxt_comment\b" >/dev/null 2>&1 ; then
XT_COMMENT=0
fi
}
check_iptables
# enable Internet sharing
if [[ "$SHARE_METHOD" == "none" ]]; then