让无线网卡同时工作在 AP 和 STA 模式

有的时候会碰到这么一种情况,带着电脑和手机出去蹭网,无奈只有一个账号,手机上了电脑就没得用了,电脑用了手机就上不了网。如果能用电脑连接 Wifi 然后再开热点给手机用该多好。一般情况下,每台笔记本里面只有一张无线网卡,按照常规的思路要一边作为 STA 连接在别的热点上,一边又要做 AP 给手机用的话似乎就非得再买一张 USB 的无线网卡了。不过现在有一种方法可以让一张无线网卡同时处于 STA 和 AP 的状态,一边作为客户端连在别的 AP 上,一边又自己作为 AP 让别的客户端来连接。

这种特殊的“一卡两用”的状态需要 WDS 的支持。WDS 是一个复杂的东西,现在只讲特定情况下的应用。一般来讲,采用 ath9k 驱动的无线网卡都是支持 WDS 的(其它基于 mac80211 的驱动不详,不过值得一试)。另外,为了能使用 WDS ,还要求 hostapd 的版本在 0.7.x 以上。

下面是一个小脚本,它将在 wlan0 上启动一个 AP ,同时生成一个新的接口 wds0 ,可供 NetworkManager 直接作为 STA 使用。

#!/bin/sh
WIFI=wlan0 # NOTE 1
PHY=phy0 # NOTE 2
WAN=wds0 # NOTE 3

# Extra NAT Module
modprobe nf_nat_pptp
modprobe nf_nat_ftp
# NOTE 4

# Config Wireless
ifconfig $WIFI up
ifconfig $WIFI 172.16.1.1/24
ifconfig $WIFI mtu 1500

# Configure dnsmasq
cat > /etc/dnsmasq.conf << EOF
dhcp-range=172.16.1.100,172.16.1.150,255.255.255.0,24h
port=0
dhcp-option=option:dns-server,8.8.8.8,8.8.4.4
interface=$WIFI
EOF
# NOTE 5

# DHCP server
service dnsmasq stop
service dnsmasq start

# AP and WDS STA
hostapd -B ./hostapd-wds.conf
iw phy $PHY interface add $WAN type wds
ifconfig $WAN hw ether b4:82:fe:54:c8:3e # NOTE 6
ifconfig $WAN up

# Enable IPv4 Forwarding
echo "1"  > /proc/sys/net/ipv4/ip_forward
iptables -P FORWARD ACCEPT

# NAT with iptables
iptables -t nat -A POSTROUTING -o $WAN -s 172.16.1.1/24 -j MASQUERADE

NOTES:

  1. wlan0 是无线网卡默认的接口名称。使用时请根据实际情况设定。对于使用基于 mac80211 架构驱动的网卡,其接口名一般是 wlanx ,系统中的第一张网卡一般是 wlan0 。稍后这个接口会被作为 AP 使用;
  2. 这是对应的无线网卡的 PHY 的名称,一般为 phy0 ,可以这样找出:先 lspci 找出无线网卡的 PCI 地址,然后 ls /sys/bus/pci/devices/[对应的完整 PCI 地址]/ieee80211 即可找出;
  3. 期望的 WDS STA 接口名称,完全依个人喜好填写,不要和已有的接口冲突即可;
  4. 加载这些额外的 module 是为了保证在 NAT 后面的 PPTP 客户端和 FTP 服务器能正常工作;
  5. dnsmasq 的配置请参考 http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq.conf.example ,本例中 dnsmasq 只做 DHCP 服务器,IP 地址范围 172.16.1.100 – 172.16.1.150 ,租期 24 小时,DNS 服务器默认为 8.8.8.8 和 8.8.4.4 ;
  6. 这里的 MAC 地址也是按照个人喜好设定的,不过不要和系统已有的任何网卡地址相同(包括无线网卡的 AP 接口)。

有关的 hostapd-wds.conf 的内容如下,请放置在该脚本的工作目录下:

auth_algs=1
beacon_int=300
channel=6 # NOTE 1
country_code=CN
ctrl_interface_group=adm
ctrl_interface=/var/run/hostapd
driver=nl80211 # NOTE 2
dtim_period=2
dump_file=/tmp/hostapd.dump
eapol_key_index_workaround=0
eap_server=0
fragm_threshold=2346
hw_mode=g #NOTE 3
ieee80211d=1
ieee80211n=1 #NOTE 4
ignore_broadcast_ssid=0
interface=wlan0 #NOTE 5
logger_stdout=-1
logger_stdout_level=2
logger_syslog=-1
logger_syslog_level=2
macaddr_acl=0
max_num_sta=16
own_ip_addr=127.0.0.1
preamble=1
rsn_pairwise=CCMP
rts_threshold=2347
ssid=dword-relay # NOTE 6
wds_sta=1
wmm_ac_be_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmax=10
wmm_ac_be_cwmin=4
wmm_ac_be_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_bk_aifs=7
wmm_ac_bk_cwmax=10
wmm_ac_bk_cwmin=4
wmm_ac_bk_txop_limit=0
wmm_ac_vi_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmax=4
wmm_ac_vi_cwmin=3
wmm_ac_vi_txop_limit=94
wmm_ac_vo_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_cwmin=2
wmm_ac_vo_txop_limit=47
wmm_enabled=1
wpa=2
wpa_gmk_rekey=7200
wpa_group_rekey=1200
wpa_passphrase=qwertyuiop #NOTE 7
wpa_ptk_rekey=600
wpa_strict_rekey=1
wps_state=0

NOTES:

  1. 在这里设置新生成的 AP 的信道,最好和 STA 界面要连接的 AP 的信道保持一致;
  2. 驱动视网卡而定,如果网卡的驱动是 ath9k 这样基于 mac80211 的驱动的话,这里选 nl80211 就可以了;
  3. 模式有 a/b/g 可选,视网卡的情况和需求而定;
  4. 是否打开 802.11n ,视网卡的情况和需求而定;
  5. 网卡 AP 界面名称;
  6. 新 AP 的 ESSID ;
  7. 新 AP 的 WPA2 密码句;
  8. 其余关于 hostapd 的配置可参考:http://hostap.epitest.fi/gitweb/gitweb.cgi?p=hostap-07.git;a=blob_plain;f=hostapd/hostapd.conf;hb=HEAD ;
  9. 关键是把 wds_sta 设置为“ 1 ”。

最后,sudo 执行脚本,然后通过 NetworkManager 让 wds0 (或者其他你设置的名字)连接上一个热点,即可一边蹭网一边共享热点了。

有图有真相:

参考:

星期五, 十一月 2nd, 2012 网络, Linux

73 条评论 针对于 让无线网卡同时工作在 AP 和 STA 模式

  • t.k.说道:

    原来STA和WDS是这个意思。学习了。
    不知道博主是不是用桌面Linux,好像Ubuntu下既做AP又连Wifi上网是可以的,而且鼠标点点设置就行了。

  • Zero Omega说道:

    AP和STA的频率不一样根本跑不起来吧。 RF芯片来回切换频率效率不会高

  • Wilder说道:

    楼主,我环境ubuntu12.04,无线网卡ar9285跟你差不多,为什么用NetworkManager,选择新建的wds接口连接不上,在ifconfig下显示mac是自己创建时设置的,但是在NetworkManager选择接口时,显示和wlan0的mac是一样的,也就默认用wlan0去连接其他AP,这样肯定连不上啊。

  • ljyang说道:

    为什么wds0和wlan0只能ifconfig up 一个,另外一个总提示设备或资源忙啊。

  • ljyang说道:

    是rt5370的一个usbwifi模块,通过iw phy0 info 查看,是支持wds功能的。mac地址我已经手动修改wds0的Mac和wlan0的mac地址不一样了。但是每次ifconfig up第二个接口的时候总是出现设备或者资源忙的信息。

    • dword1511说道:

      刚刚搜了下,RT5370 貌似只有 Ralink 自己的私有 STA 驱动吧,不知道单独开 AP 能否成功?对这类驱动不了解,但是一般貌似可玩性有限。

  • ljyang说道:

    谢谢你的回复,我刚买的ar9271,还没有到,买回来再试试。谢谢哦

  • czj说道:

    有一个问题,我的笔记本的无线网卡是AR9462,运行脚本后成功建立了一个wifi中继热点,其他手机连接笔记本新建立的那个热点(就是wlan0建立的)上网正常,但是笔记本自己反而无法上网了(wds0,笔记本连接着无线路由器),你的笔记本也能正常上网吗?

    • dword1511说道:

      当初就是为了笔记本和其他设备都能上网才这样的。可以看看是不是 DNS 的问题。当时我用的时候是没有问题的。

      • czj说道:

        DNS看了一下连接无线路由器的wds0这里的DNS就是运营商的DNS,建立AP热点的wlan0这里的DNS是配置的Google的8.8.8.8 和 8.8.4.4

        • dword1511说道:

          route -n
          traceroute 8.8.8.8
          nslookup google.com
          看看结果如何?

          • czj说道:

            首先,脚本运行后,terminal里输出的内容:
            * Stopping DNS forwarder and DHCP server dnsmasq * (not running)
            * Starting DNS forwarder and DHCP server dnsmasq [ OK ]
            Configuration file: ./hostapd-wds.conf
            Failed to update rate sets in kernel module
            Using interface wlan0 with hwaddr e8:03:9a:cd:c9:91 and ssid ‘mars’
            random: Only 18/20 bytes of strong random data available from /dev/random
            random: Not enough entropy pool available for secure operations
            WPA: Not enough entropy in random pool for secure operations – update keys later when the first station connects
            SIOCSIFFLAGS: Link has been severed

          • czj说道:

            然后,route -n的结果:
            内核 IP 路由表
            目标 网关 子网掩码 标志 跃点 引用 使用 接口
            0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 wds0
            169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 wds0
            192.168.1.0 0.0.0.0 255.255.255.0 U 9 0 0 wds0

          • czj说道:

            最后,traceroute 8.8.8.8的结果:
            traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
            1 * * *
            2 * * *
            3 * * *
            4 * * *
            5 * * *
            (共30行×××)

            nslookup google.com
            ;; connection timed out; no servers could be reached

          • dword1511说道:

            路由表看起来没问题。traceroute 和 nslookup 的结果呢?

          • dword1511说道:

            那能上网的那些设备上能 trace 吗?笔电上 192.168.1.1 能 ping 通吗?arp -an 结果如何?iptables -t filter -L 和 iptables -t nat -L 呢?

          • czj说道:

            脚本运行后输出的最后一句话SIOCSIFFLAGS: Link has been severed
            连接已经被中断,是不是这个造成的呢?

          • dword1511说道:

            这个应该是 hostapd 的输出,不过 ifconfig 也有可能。看看 ifconfig -a ?

          • dword1511说道:

            另外两个接口必须处于同一信道。不过既然后面的设备能上网,我猜应该是 NM 把 MAC 搞砸了

          • czj说道:

            我配置hostapd-wds.conf的时候,是把信道配成与家里无线路由器的信道一致的

          • czj说道:

            笔记本上192.168.1.1可以ping通,另外那些连接笔记本热点的设备是安卓手机,不知道怎么trace

            arp -an的输出:
            ? (192.168.1.1) 位于 14:e6:e4:c5:76:72 [ether] 在 wds0

            sudo iptables -t filter -L的输出:
            Chain INPUT (policy ACCEPT)
            target prot opt source destination

            Chain FORWARD (policy ACCEPT)
            target prot opt source destination

            Chain OUTPUT (policy ACCEPT)
            target prot opt source destination

            sudo iptables -t nat -L的输出:
            Chain PREROUTING (policy ACCEPT)
            target prot opt source destination

            Chain INPUT (policy ACCEPT)
            target prot opt source destination

            Chain OUTPUT (policy ACCEPT)
            target prot opt source destination

            Chain POSTROUTING (policy ACCEPT)
            target prot opt source destination
            MASQUERADE all — 172.16.1.0/24 anywhere

          • czj说道:

            ipconfig -a的输出:

            eth0 Link encap:以太网 硬件地址 e8:03:9a:be:4a:9d
            UP BROADCAST MULTICAST MTU:1500 跃点数:1
            接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
            发送数据包:0 错误:0 丢弃:0 过载:0 载波:0
            碰撞:0 发送队列长度:1000
            接收字节:0 (0.0 B) 发送字节:0 (0.0 B)

            lo Link encap:本地环回
            inet 地址:127.0.0.1 掩码:255.0.0.0
            inet6 地址: ::1/128 Scope:Host
            UP LOOPBACK RUNNING MTU:65536 跃点数:1
            接收数据包:3234 错误:0 丢弃:0 过载:0 帧数:0
            发送数据包:3234 错误:0 丢弃:0 过载:0 载波:0
            碰撞:0 发送队列长度:0
            接收字节:434732 (434.7 KB) 发送字节:434732 (434.7 KB)

            mon.wlan0 Link encap:未指定 硬件地址 E8-03-9A-CD-C9-91-3A-30-00-00-00-00-00-00-00-00
            UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
            接收数据包:2528 错误:0 丢弃:0 过载:0 帧数:0
            发送数据包:0 错误:0 丢弃:0 过载:0 载波:0
            碰撞:0 发送队列长度:1000
            接收字节:675602 (675.6 KB) 发送字节:0 (0.0 B)

            wds0 Link encap:以太网 硬件地址 b4:82:fe:54:c8:3e
            inet 地址:192.168.1.109 广播:192.168.1.255 掩码:255.255.255.0
            inet6 地址: fe80::b682:feff:fe54:c83e/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
            接收数据包:20 错误:0 丢弃:0 过载:0 帧数:0
            发送数据包:77 错误:0 丢弃:0 过载:0 载波:0
            碰撞:0 发送队列长度:1000
            接收字节:2346 (2.3 KB) 发送字节:13555 (13.5 KB)

            wlan0 Link encap:以太网 硬件地址 e8:03:9a:cd:c9:91
            inet 地址:172.16.1.1 广播:172.16.1.255 掩码:255.255.255.0
            inet6 地址: fe80::ea03:9aff:fecd:c991/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST MTU:1500 跃点数:1
            接收数据包:9921 错误:0 丢弃:0 过载:0 帧数:0
            发送数据包:11802 错误:0 丢弃:0 过载:0 载波:0
            碰撞:0 发送队列长度:1000
            接收字节:8050202 (8.0 MB) 发送字节:2152035 (2.1 MB)

          • dword1511说道:

            这就很奇怪了,MAC 没问题,流量看起来很正常,而且 ping 网关还能 ping 通。照理说应该没有问题啊,除非网关那边做了过滤什么的。

          • dword1511说道:

            这样似乎就只能用 tcpdump 或者 wireshark 在各个端口上抓包看看到底发生了什么了。你可以自己尝试一下,我感觉我已经帮不了你了。

          • czj说道:

            哦,我试试吧,我也觉得很奇怪。另外,你运行脚本的时候也会输出这句话吗? SIOCSIFFLAGS: Link has been severed

          • dword1511说道:

            没。我用的 AR9280 ,3.2.0 的内核。

          • dword1511说道:

            你这是新买的本子吧?网卡看起来很牛逼

          • czj说道:

            嗯,笔记本是去年7月买的三星的AMD超级本–三星535U4C-S01,ubuntu的系统装的是ubuntukylin13.04

          • czj说道:

            这个笔记本在win7、win8下都自带的建立wifi repeater的功能(用Connectify也可以建立),在ubuntu下就得自己弄了。xp下不能建立wifi repeater,不过可以通过蓝牙4.0把wifi连接的网络共享出来给Android4.0以上的手机上网或者双环共享给ios设备上网

  • czj说道:

    我没有试过苹果的设备,像Macbook Pro我知道是可以在插网线的时候通过Mac OS X自带的网络共享的功能建立一个软AP热点,不过Macbook上应该不能连接wifi的同时再把wifi发射出去吧?你试过吗?

  • czj说道:

    我用的系统是ubuntu13.04,你测试的时候用的是什么系统什么版本的呢?或许与系统的差异有关?

    • dword1511说道:

      是这样的,较新的 ubuntu 上的 nm 会启动一个 dnsmasq 作为 DNS 缓存使用,而你启动 AP 的时候 dnsmasq 被配置成 DHCP 服务器并重启,所以缓存服务器就没了,DNS 查找失败。所以要关掉 nm 的 dnsmasq 支持。当然,也可以研究别的 DHCP 服务程序。

      • czj说道:

        哦,这样关吗?他这都把dnsmasq卸载掉了吧?
        2.关闭dnsmasq
        注释掉sudo vi /etc/NetworkManager/NetworkManager.conf里面的dns=dnsmasq
        重启NM:sudo restart network-manager
        sudo apt-get install dnsmasq(NM用的仅是dnsmasq的核心组件,默认没有全部安装,我是先安装后卸载的,只要能解决问题就行)
        sudo apt-get remove dnsmasq

  • ARM Linux说道:

    使用的是ARM9+Linux,WiFi芯片使用的是RT3070.
    /apps/tools >: uname -a
    Linux CoherentPlus 3.4.0 #321 Thu Jul 25 22:18:07 CST 2013 armv5tejl GNU/Linux
    /apps/tools >: lsusb
    Bus 001 Device 003: ID 148f:3070

    单独使用hostapd和wpa_supplicant来作AP和联网都能正常工作。现在想测试hostapd的WDS功能,按照hostapd的说法是支持mac80211驱动的。但按照你的这个说明来作WDS却不可以,mac地址并不冲突,但是wds0总是不能up:
    /apps/tools >: ifconfig wds0
    wds0 Link encap:Ethernet HWaddr B4:82:FE:54:C8:3E
    inet addr:192.168.1.128 Bcast:192.168.1.255 Mask:255.255.255.0
    BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

    /apps/tools >: ifconfig wlan0
    wlan0 Link encap:Ethernet HWaddr 00:0C:43:30:73:5C
    inet addr:192.168.10.1 Bcast:192.168.10.255 Mask:255.255.255.0
    UP BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:46611 errors:0 dropped:0 overruns:0 frame:0
    TX packets:51504 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:5574993 (5.3 MiB) TX bytes:45728910 (43.6 MiB)

    /apps/tools >: ifconfig wds0 up
    ifconfig: SIOCSIFFLAGS: Link has been severed
    /apps/tools >: ifconfig wlan0 up
    /apps/tools >: ifconfig wlan0 down
    /apps/tools >: ifconfig wds0 up
    ifconfig: SIOCSIFFLAGS: Link has been severed

    iw list命令显示是支持WDS功能的:
    Supported interface modes:
    * IBSS
    * managed
    * AP
    * AP/VLAN
    * WDS
    * monitor

  • 韩光说道:

    先膜拜一下博主大神,你的整个hostapd-wds.conf还有部分的脚本解决了困扰了咱一个月的大问题
    现在共享已经成功,实在太谢谢了
    但还有一些小问题
    注意到博主在你的脚本里面是先打开了dhcp服务器,再用nm进行联网,但在开启dhcp服务器之后我的无线网卡就无法再从另外的ap处收到IP地址了,dhcp服务器我用的是dhcpd,不知道和这个有关系没有
    还有我的hostapd运行起来之后用ip link查看,多出来一块虚拟网卡mon.wlp3s0,但实际设置ip地址等操作还是需要在wlp3s0处设置(因为我系统用的systemd所以网卡名称比较奇葩),就想问问是不是大家的都是这样

  • zhou说道:

    我是用的ubuntu12.04,内核3.8.0-19-generic,安装你的方法,虚拟出的wds0 使用命令ifconfig wds0 up 根本就起不来,输出错误SIOCSIFFLAGS: Device or resource busy,请问是怎么回事啊,急急急急啊!!!!!!

  • superone说道:

    你号,咨询下,我用ifconfig wds0 up时输出错误SIOCSIFFLAGS: Device or resource busy,wds0的MAC地址我已经修改了,我用的是rt2800驱动。问下是否只能使用ath9k的驱动呢?还有你用的是哪个型号的无线网卡?非常感谢!

  • aaxx254说道:

    大大,你好。我想用路由器桥接cmcc的网络可以吗?要怎么弄的。路由器支持wds,但是用的人比较多,一个人一帐号web登陆,但是测试的结果是只要登陆一个帐号就所有人都可以上网了。

    • dword1511说道:

      CMCC 的路由可能是拿 station 的 MAC 做的访问控制,所以会出现同一路由器后面一人认证全部可以联网的状况。iptables 里面貌似有可以伪装 MAC 地址的工具,没研究过。

  • 留个言呗