iptables NAT rule: do not masquerade client to client connections

This commit is contained in:
garywill 2018-08-31 18:41:06 +08:00 committed by garywill
parent 4022d798b0
commit 7815bce574
2 changed files with 51 additions and 78 deletions

View File

@ -1,7 +1,10 @@
# Linux-router # Linux-router
Share your Linux's Internet access to other devices. Works on wired, wireless and virtual networks. Share your Linux's Internet access to other devices.
The goal is to easily set/unset your Linux PC/embedded device as a gateway/hotspot/transparent proxy. It wraps the complicated `iptables`, `dnsmasq` etc. stuff. Use in one command, restore by `control-c`.
It works on wired, wireless and virtual networks.
## Features ## Features
@ -11,58 +14,46 @@ Basic features:
- Share Internet to the sub-network - Share Internet to the sub-network
- DHCP server - DHCP server
- DNS server - DNS server
- Transparent proxy (redsocks) (with DNS proxy) - Creating Wifi hotspot:
- Channel selecting
- Choose encryptions: WPA2/WPA, WPA2, WPA, No encryption
- Hidden SSID
- Create AP on the same interface you are getting Internet (require same channel)
- Transparent proxy (redsocks)
- DNS proxy
Creating Wifi hotspot: **For many other features, see below [CLI usage](#cli-usage-and-other-features)**
- Channel selecting ### Useful in these situations
- Choose encryptions: WPA2/WPA, WPA2, WPA, No encryption
- Hidden SSID
- Create AP on the same interface you are getting Internet (require same channel)
For many other features, see below CLI usage.
Useful in these situations:
``` ```
Internet ----(eth0/wlan0)-Linux-(wlanX)AP Internet----(eth0/wlan0)-Linux-(wlanX)AP
| |--client
|----client |--client
|
|----client
``` ```
``` ```
Internet Internet
Wifi AP(no DHCP) | Wifi AP(no DHCP) |
| |
|----(wlan1)-Linux-(eth0/wlan0)------ |----(wlan1)-Linux-(eth0/wlan0)------
| (DHCP) | (DHCP)
| |--client
|----client |--client
|
|----client
``` ```
``` ```
Internet Internet
Switch | Switch |
| |
|---(eth1)-Linux-(eth0/wlan0)-------- |---(eth1)-Linux-(eth0/wlan0)--------
| |--client
|----client |--client
|
|----client
``` ```
``` ```
Internet ----(eth0/wlan0)-Linux-(eth1)--------Another PC Internet----(eth0/wlan0)-Linux-(eth1)------Another PC
``` ```
``` ```
Internet ----(eth0/wlan0)-Linux-(virtual interface)-----VM guests/container guests Internet----(eth0/wlan0)-Linux-(virtual interface)-----VM guests/container guests
``` ```
## Usage ## Usage
@ -79,12 +70,10 @@ Internet ----(eth0/wlan0)-Linux-(virtual interface)-----VM guests/container gues
# lnxrouter --ap wlan0 MyAccessPoint --password MyPassPhrase # lnxrouter --ap wlan0 MyAccessPoint --password MyPassPhrase
``` ```
### Make a LAN without Internet ### LAN without Internet
``` ```
# lnxrouter -i eth1 -n # lnxrouter -i eth1 -n
```
```
# lnxrouter --ap wlan0 MyAccessPoint --password MyPassPhrase -n # lnxrouter --ap wlan0 MyAccessPoint --password MyPassPhrase -n
``` ```
@ -100,12 +89,12 @@ In `torrc`
TransPort 0.0.0.0:9040 TransPort 0.0.0.0:9040
DNSPort 0.0.0.0:9053 DNSPort 0.0.0.0:9053
``` ```
### Using with LXC ### Use with LXC
Create a bridge Create a bridge
``` ```
# brctl addbr lxcbr1 # brctl addbr lxcbr1
``` ```
In LXC container's `config` In LXC container `config`
``` ```
lxc.network.type = veth lxc.network.type = veth
lxc.network.flags = up lxc.network.flags = up
@ -115,7 +104,7 @@ lxc.network.hwaddr = xx:xx:xx:xx:xx:xx
``` ```
# lnxrouter -i lxcbr1 # lnxrouter -i lxcbr1
``` ```
### Using with VirtualBox ### Use with VirtualBox
On VirtualBox's global settings, create a host-only network `vboxnet1` with DHCP disabled. On VirtualBox's global settings, create a host-only network `vboxnet1` with DHCP disabled.
``` ```
# lnxrouter -i vboxnet1 # lnxrouter -i vboxnet1
@ -136,7 +125,7 @@ Options:
Usually use with --dns-proxy Usually use with --dns-proxy
-g <gateway> Set Gateway IPv4 address, netmask is /24 (default: 192.168.18.1) -g <gateway> Set Gateway IPv4 address, netmask is /24 (default: 192.168.18.1)
--dns-proxy <port> Redirect 53 port to DNS proxy port. dnsmasq DNS is disabled --dns-proxy <port> Redirect incoming 53 port to DNS proxy port. dnsmasq DNS is disabled
--no-serve-dns dnsmasq DNS disabled --no-serve-dns dnsmasq DNS disabled
--no-dnsmasq Disable dnsmasq server completely (dhcp and dns) --no-dnsmasq Disable dnsmasq server completely (dhcp and dns)
--log-dns Show dnsmasq DNS server query log --log-dns Show dnsmasq DNS server query log
@ -189,7 +178,7 @@ Options:
``` ```
### Ddependencies ## Dependencies
- bash - bash
- procps or procps-ng - procps or procps-ng
- iproute2 - iproute2
@ -208,6 +197,8 @@ Wifi hotspot:
- Option to ban private network access - Option to ban private network access
- IPv6 support - IPv6 support
- Option to random MAC, IP, SSID, password - Option to random MAC, IP, SSID, password
- Option to specify out-going interface
- Option to catch and redirect all dns connections
## Thanks ## Thanks

View File

@ -1,23 +1,8 @@
#!/bin/bash #!/bin/bash
# general dependencies:
# bash (to run this script)
# procps or procps-ng
# iproute2
# dnsmasq
# iptables
# wifi ap:
# hostapd
# iw
# iwconfig (you only need this if 'iw' can not recognize your adapter)
# haveged (optional)
VERSION=0.5.0 VERSION=0.5.0
PROGNAME="$(basename $0)" PROGNAME="$(basename $0)"
# make sure that all command outputs are in english
# so we can parse them correctly
export LC_ALL=C export LC_ALL=C
# all new files and directories must be readable only by root. # all new files and directories must be readable only by root.
@ -26,9 +11,9 @@ SCRIPT_UMASK=0077
umask $SCRIPT_UMASK umask $SCRIPT_UMASK
usage() { usage() {
echo "$PROGNAME $VERSION (https://github.com/garywill/linux-router)" echo "linux-router $VERSION (https://github.com/garywill/linux-router)"
echo "Share your Linux's Internet access to other devices. " echo "Share your Linux's Internet access to other devices. "
echo "Work on wired, wireless and virtual networks." echo "Works on wired, wireless and virtual networks."
echo echo
echo "Usage: "$PROGNAME" [options] " echo "Usage: "$PROGNAME" [options] "
echo echo
@ -36,23 +21,17 @@ usage() {
echo " -h, --help Show this help" echo " -h, --help Show this help"
echo " --version Print version number" echo " --version Print version number"
echo echo
echo " -i <interface> Interface to share Internet to. An NATed subnet is made upon it."
echo " To create Wifi hotspot use '--ap' instead"
#echo " -m <method> Method for Internet sharing."
#echo " Use: 'nat' for NAT (default)"
#echo " 'redsocks' for transparent proxy. Usually use with --dns-proxy"
#echo " 'none' for no Internet sharing (equivalent to -n)"
echo " -i <interface> Interface to share Internet to. An NATed subnet will be made on it."
echo " To create Wifi hotspot use --ap instead"
echo " -n Disable Internet sharing" echo " -n Disable Internet sharing"
echo " --tp <port> Transparent proxy (redsocks), redirect tcp and udp traffic to port." echo " --tp <port> Transparent proxy (redsocks), redirect tcp and udp traffic to port."
echo " Usually use with --dns-proxy" echo " Usually use with --dns-proxy"
echo echo
echo " -g <gateway> Set Gateway IPv4 address, netmask is /24 (default: 192.168.18.1)" echo " -g <gateway> Set Gateway IPv4 address, netmask is /24 (default: 192.168.18.1)"
echo " --dns-proxy <port> Redirect 53 port to DNS proxy port. dnsmasq DNS is disabled" echo " --dns-proxy <port> Redirect incoming port 53 to DNS proxy port. DNS server is disabled"
echo " --no-serve-dns dnsmasq DNS disabled" echo " --no-serve-dns Disable DNS server"
echo " --no-dnsmasq Disable dnsmasq server completely (dhcp and dns)" echo " --no-dnsmasq Disable dnsmasq server completely (DHCP and DNS)"
echo " --log-dns Show dnsmasq DNS server query log" echo " --log-dns Show DNS server query log"
echo " --dhcp-dns <IP1[,IP2]>|no" echo " --dhcp-dns <IP1[,IP2]>|no"
echo " Set DNS offered by DHCP, or no DNS offered (default: gateway as DNS)" echo " Set DNS offered by DHCP, or no DNS offered (default: gateway as DNS)"
echo " -d DNS server will take into account /etc/hosts" echo " -d DNS server will take into account /etc/hosts"
@ -883,12 +862,12 @@ iptables_()
start_nat() { start_nat() {
echo echo
echo "iptables: NAT " echo "iptables: NAT "
iptables_ -v -t nat -I POSTROUTING -s ${GATEWAY%.*}.0/24 -j MASQUERADE || die iptables_ -v -t nat -I POSTROUTING -s ${GATEWAY%.*}.0/24 ! -d ${GATEWAY%.*}.0/24 ! -o ${SUBNET_IFACE} -j MASQUERADE || die
iptables_ -v -I FORWARD -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT || die iptables_ -v -I FORWARD -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT || die
iptables_ -v -I FORWARD -o ${SUBNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT || die iptables_ -v -I FORWARD -o ${SUBNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT || die
} }
stop_nat() { stop_nat() {
iptables_ -t nat -D POSTROUTING -s ${GATEWAY%.*}.0/24 -j MASQUERADE iptables_ -t nat -D POSTROUTING -s ${GATEWAY%.*}.0/24 ! -d ${GATEWAY%.*}.0/24 ! -o ${SUBNET_IFACE} -j MASQUERADE
iptables_ -D FORWARD -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT iptables_ -D FORWARD -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT
iptables_ -D FORWARD -o ${SUBNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT iptables_ -D FORWARD -o ${SUBNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT
} }
@ -1043,10 +1022,11 @@ clean_iptables() {
cleanup() { cleanup() {
echo echo
echo -n "Doing cleanup.. " echo
echo "Doing cleanup.. "
clean_iptables clean_iptables
_cleanup 2> /dev/null _cleanup 2> /dev/null
echo "done" echo "Cleaning up done"
} }
die() { die() {
@ -1058,6 +1038,7 @@ die() {
} }
clean_exit() { clean_exit() {
echo "clean_exit()"
# send clean_exit signal to the main process # send clean_exit signal to the main process
[[ $BASHPID -ne $$ ]] && kill -USR1 $$ [[ $BASHPID -ne $$ ]] && kill -USR1 $$
# we don't need to call cleanup because it's traped on EXIT # we don't need to call cleanup because it's traped on EXIT
@ -1432,7 +1413,7 @@ if [[ $WIFI_IFACE ]]; then
# in NetworkManager 0.9.9 and above we can set the interface as unmanaged without # in NetworkManager 0.9.9 and above we can set the interface as unmanaged without
# the need of MAC address, so we set it before we create the virtual interface. # the need of MAC address, so we set it before we create the virtual interface.
if networkmanager_is_running && [[ $NM_OLDER_VERSION -eq 0 ]]; then if networkmanager_is_running && [[ $NM_OLDER_VERSION -eq 0 ]]; then
echo -n "Network Manager found, set ${VWIFI_IFACE} as unmanaged device... " echo "Network Manager found, set ${VWIFI_IFACE} as unmanaged device... "
networkmanager_add_unmanaged ${VWIFI_IFACE} networkmanager_add_unmanaged ${VWIFI_IFACE}
# do not call networkmanager_wait_until_unmanaged because interface does not # do not call networkmanager_wait_until_unmanaged because interface does not
# exist yet # exist yet
@ -1441,14 +1422,14 @@ if [[ $WIFI_IFACE ]]; then
if is_wifi_connected ${WIFI_IFACE}; then if is_wifi_connected ${WIFI_IFACE}; then
WIFI_IFACE_FREQ=$(iw dev ${WIFI_IFACE} link | grep -i freq | awk '{print $2}') WIFI_IFACE_FREQ=$(iw dev ${WIFI_IFACE} link | grep -i freq | awk '{print $2}')
WIFI_IFACE_CHANNEL=$(ieee80211_frequency_to_channel ${WIFI_IFACE_FREQ}) WIFI_IFACE_CHANNEL=$(ieee80211_frequency_to_channel ${WIFI_IFACE_FREQ})
echo -n "${WIFI_IFACE} is already associated with channel ${WIFI_IFACE_CHANNEL} (${WIFI_IFACE_FREQ} MHz)" echo "${WIFI_IFACE} already in channel ${WIFI_IFACE_CHANNEL} (${WIFI_IFACE_FREQ} MHz)"
if is_5ghz_frequency $WIFI_IFACE_FREQ; then if is_5ghz_frequency $WIFI_IFACE_FREQ; then
FREQ_BAND=5 FREQ_BAND=5
else else
FREQ_BAND=2.4 FREQ_BAND=2.4
fi fi
if [[ $WIFI_IFACE_CHANNEL -ne $CHANNEL ]]; then if [[ $WIFI_IFACE_CHANNEL -ne $CHANNEL ]]; then
echo ", fallback to channel ${WIFI_IFACE_CHANNEL}" echo "Channel fallback to ${WIFI_IFACE_CHANNEL}"
CHANNEL=$WIFI_IFACE_CHANNEL CHANNEL=$WIFI_IFACE_CHANNEL
else else
echo echo
@ -1457,7 +1438,7 @@ if [[ $WIFI_IFACE ]]; then
VIRTDIEMSG="Maybe your WiFi adapter does not fully support virtual interfaces. VIRTDIEMSG="Maybe your WiFi adapter does not fully support virtual interfaces.
Try again with --no-virt." Try again with --no-virt."
echo -n "Creating a virtual WiFi interface... " echo "Creating a virtual WiFi interface... "
if iw dev ${WIFI_IFACE} interface add ${VWIFI_IFACE} type __ap; then if iw dev ${WIFI_IFACE} interface add ${VWIFI_IFACE} type __ap; then
# now we can call networkmanager_wait_until_unmanaged # now we can call networkmanager_wait_until_unmanaged
@ -1581,7 +1562,7 @@ fi
#=================================================== #===================================================
if networkmanager_exists && ! networkmanager_iface_is_unmanaged ${SUBNET_IFACE}; then if networkmanager_exists && ! networkmanager_iface_is_unmanaged ${SUBNET_IFACE}; then
echo -n "Network Manager found, set ${SUBNET_IFACE} as unmanaged device... " echo "Network Manager found, set ${SUBNET_IFACE} as unmanaged device... "
networkmanager_add_unmanaged ${SUBNET_IFACE} networkmanager_add_unmanaged ${SUBNET_IFACE}
if networkmanager_is_running; then if networkmanager_is_running; then
@ -1699,10 +1680,11 @@ if [[ $WIFI_IFACE ]]; then
if [[ $NO_HAVEGED -eq 0 ]]; then if [[ $NO_HAVEGED -eq 0 ]]; then
haveged_watchdog & haveged_watchdog &
HAVEGED_WATCHDOG_PID=$! HAVEGED_WATCHDOG_PID=$!
echo "haveged_watchdog PID: $HAVEGED_WATCHDOG_PID"
fi fi
# start access point # start access point
echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl" #echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl"
# start hostapd (use stdbuf when available for no delayed output in programs that redirect stdout) # start hostapd (use stdbuf when available for no delayed output in programs that redirect stdout)
STDBUF_PATH=`which stdbuf` STDBUF_PATH=`which stdbuf`
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then