Linux 如何连接着 Wi-Fi 的同时创建热点?

类似的,windows 7 自带这种功能,大概是虚拟出一块网卡,详情看这里: Windows 如何实现通过一块无线网卡同时连接 Wi-Fi 热点并且无线共享网络? 那linux如何创建呢?是连接着wifi并且同时创建热点,不是插上网线再分享热点。 打算将树莓派打造成一个路由器,要有普遍的实现方法,最好能使用命令实现。 (顺便说一下,那些路由器可以刷了openwrt之类的嵌入式linux,可以实现这一点,如果不是硬件的原因,理论上linux也可以实现…
关注者
108
被浏览
9,527

4 个回答

这个方法有一个缺点,要先执行脚本开了热点后再联网。先联网那个脚本就启动不了了不知道为什么。

首先需要网卡支持ap模式;需要电脑上先装有这些:
# dependencies:
#    bash (to run this script)
#    util-linux (for getopt)
#    hostapd
#    dnsmasq
#    iptables
#    iproute2
#    haveged (optional)

楼主应该懂一些简单shell吧,有人写好了一个creat_ap脚本,都不难,你大看看看就知道怎么回事。参考:Software access point (简体中文)

1. 脚本
#!/bin/bash

# 增加一个虚拟网络接口并设置一个mac地址
sudo iw dev wlp9s0 interface add wlp9s0_ap type __ap
sudo ip link set dev wlp9s0_ap address 04:e2:b9:17:18:72

# 注意creat_ap脚本的位置,系统要能找到,吧creat_ap文件丢到 /bin 里去吧
sudo creat_ap -c 11 wlp9s0_ap wlp9s0 youssid yourpasswowd

2. creat_ap文件内容
#!/bin/bash

# dependencies:
#    bash (to run this script)
#    util-linux (for getopt)
#    hostapd
#    dnsmasq
#    iptables
#    iproute2
#    haveged (optional)

usage() {
    echo "Usage: $(basename $0) [options] <wifi-interface> <interface-with-internet> <access-point-name> [<passphrase>]"
    echo
    echo "Options:"
    echo "  -h, --help          Show this help"
    echo "  -c <channel>        Channel number (default: 1)"
    echo "  -w <WPA version>    Use 1 for WPA, use 2 for WPA2, use 1+2 for both (default: 1+2)"
    echo "  -g <gateway>        IPv4 Gateway for the Access Point (default: 192.168.12.1)"
    echo "  -d                  DNS server will take into account /etc/hosts (default: disabled)"
    echo
    echo "Example:"
    echo "  $(basename $0) wlan0 eth0 MyAccessPoint MyPassPhrase"
}

get_macaddr() {
    ip link show "$1" | sed -n 's/.*ether \([0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]\) .*/\1/p'
}

ARGS=$(getopt -o hc:w:g:d -l "help" -n $(basename $0) -- "$@")
[[ $? -ne 0 ]] && exit 1
eval set -- "$ARGS"

CHANNEL=1
GATEWAY=192.168.12.1
WPA_VERSION=1+2
ETC_HOSTS=0

while :; do
    case "$1" in
        -h|--help)
            usage
            exit 1
            ;;
        -c)
            shift
            if [[ -n "$1" ]]; then
                CHANNEL="$1"
                shift
            fi
            ;;
        -w)
            shift
            if [[ -n "$1" ]]; then
                WPA_VERSION="$1"
                shift
            fi
            ;;
        -g)
            shift
            if [[ -n "$1" ]]; then
                GATEWAY="$1"
                shift
            fi
            ;;
        -d)
            shift
            ETC_HOSTS=1
            ;;
        --)
            shift
            break
            ;;
    esac
done

if [[ $# -ne 3 && $# -ne 4 ]]; then
    usage
    exit 1
fi

WIFI_IFACE=$1
INTERNET_IFACE=$2
SSID=$3
PASSPHRASE=$4

if [[ $(id -u) -ne 0 ]]; then
    echo "You must run it as root."
    exit 1
fi

CONFDIR=$(mktemp -d /tmp/create_ap.${WIFI_IFACE}.conf.XXXXXXXX)
echo "Config dir: $CONFDIR"

# hostapd config
cat << EOF > $CONFDIR/hostapd.conf
ssid=${SSID}
interface=${WIFI_IFACE}
driver=nl80211
hw_mode=g
channel=${CHANNEL}

ctrl_interface=$CONFDIR/hostapd_ctrl
ctrl_interface_group=0
EOF

if [[ -n "$PASSPHRASE" ]]; then
    [[ "$WPA_VERSION" == "1+2" || "$WPA_VERSION" == "2+1" ]] && WPA_VERSION=3
    cat << EOF >> $CONFDIR/hostapd.conf
wpa=${WPA_VERSION}
wpa_passphrase=$4
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOF
fi

# dnsmasq config (dhcp + dns)
cat << EOF > $CONFDIR/dnsmasq.conf
interface=${WIFI_IFACE}
bind-interfaces
dhcp-range=${GATEWAY%.*}.1,${GATEWAY%.*}.254,255.255.255.0,24h
dhcp-option=option:router,${GATEWAY}
EOF

[[ $ETC_HOSTS -eq 0 ]] && echo no-hosts >> $CONFDIR/dnsmasq.conf

# enable interface
ip link set down dev ${WIFI_IFACE}
ip addr flush ${WIFI_IFACE}
ip link set up dev ${WIFI_IFACE}
ip addr add ${GATEWAY}/24 dev ${WIFI_IFACE}

# enable NAT
iptables -t nat -A POSTROUTING -o ${INTERNET_IFACE} -j MASQUERADE
iptables -A FORWARD -i ${WIFI_IFACE} -j ACCEPT
OLD_IP_FORWARD=$(cat /proc/sys/net/ipv4/ip_forward)
echo 1 > /proc/sys/net/ipv4/ip_forward

# boost low-entropy
if [[ $(cat /proc/sys/kernel/random/entropy_avail) -lt 1000 ]]; then
    which haveged > /dev/null 2>&1 && {
        haveged -w 1024 -p $CONFDIR/haveged.pid
    }
fi

# start dns + dhcp server
dnsmasq -C $CONFDIR/dnsmasq.conf -x $CONFDIR/dnsmasq.pid

# start access point
echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl"
hostapd $CONFDIR/hostapd.conf || {
    echo
    echo "Hostapd failed to run, maybe a program is interfering."
    echo "If you use NetworkManager then add the following in"
    echo "/etc/NetworkManager/NetworkManager.conf and retry."
    echo "Don't forget to remove it after you finish."
    echo
    echo "[keyfile]"
    echo "unmanaged-devices=mac:$(get_macaddr "$WIFI_IFACE")"
    echo
}

# exiting
for x in $CONFDIR/*.pid; do
    kill -9 $(cat $x)
done
rm -rf $CONFDIR
iptables -t nat -D POSTROUTING -o ${INTERNET_IFACE} -j MASQUERADE
iptables -D FORWARD -i ${WIFI_IFACE} -j ACCEPT
echo $OLD_IP_FORWARD > /proc/sys/net/ipv4/ip_forward
ip link set down dev ${WIFI_IFACE}
ip addr flush ${WIFI_IFACE}
exit 0
首先你的网卡要支持ap模式而不是adhoc,然后直接在网络管理器里面配置一下就可以了,如果是纯命令行请务必关掉网络管理器,否则一些设置不会生效,说起来就是,1.设定sysctl,ipv4_forwarding神马的等于1; 2,增加一个网络接口,注意是网络接口。3,设定iptables