I have a WiFi Access Point connected to a Linux Router. The Router is itself connected to the Internet. For multiple reasons (mostly to control security and quality of service), I want to force all the users' traffic to go through the Linux router, even the traffic between users.
To do this, I disabled station-to-station communications in the AP (I use a D-Link DWL-7200 AP). Here's how I configured the AP:
ssh admin@accesspoint1
D-Link Access Point wlan1 -> set sta2sta disable
D-Link Access Point wlan1 -> reboot
This works fine: wireless users cannot communicate with each other anymore. At least not directly. My goal is to force the traffic up to the router and back.
To do that, I enabled proxy-arp in the Linux Router:
echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp
Here's the big picture.
10.0.0.0/8 subnet
____________________|______________________
/ \
| |
(sta2sta disabled)
UserA----------------AP---------------------Router-------------------Internet
10.0.0.55 / eth1 eth0
/ 10.0.0.1 203.0.113.15
/ proxy-arp enabled
UserB____________/
10.0.0.66
Here's what I hoped would happen if UserA pinged UserB:
- UserA tries to ping 10.0.0.66
- so UserA sends ARP broadcast saying "Who has 10.0.0.66?"
- Access point lets the request through to the router (but not to UserB, because sta2sta is disabled)
- the router receives the request, and because proxy-arp is enabled on eth1, it should answer "Send packets for 10.0.0.66 to me (router's MAC address)".
- the access point should receive the answer and relay it to UserA.
- then the UserA should send the actual ping packet to the router's MAC address
- the packet should go through the AP to the router
- The router should route it back to eth1, by changing the destination MAC address to that of UserB (doing an ARP request if needed), and changing the source MAC address to its own.
- The packet should reach the AP and be relayed to UserB.
- UserB should reply to the ping request.
- the reply should go through the AP to the router.
- the reply should be routed to UserA.
- and it should go through the AP and reach UserA.
Unfortunately, this whole dream fails at step 4, because the Linux router receives the ARP request but fails to answer it. From what I read on the Internet, it seems that this is normal: proxy-ARP is not really designed to be used in this kind of setup. To be more precise: the router does not answer ARP requests for hosts that are on the same interface as the ARP request came from. In this case, the ARP request comes from eth1, but it says "Who has IP 10.0.0.66?", and host 10.0.0.66 is on interface eth1.
I understand why this is a good default behaviour, because if sta2sta was not disabled in the AP, UserA would receive an ARP response from the router and another ARP response from UserB. But in my case, I believe it would make perfect sense to answer each and every ARP request, even for hosts on the same interface.
Is there any way I can work around this default proxy-arp behaviour?
What you want is actually possible, but requires a pretty recent Linux kernel (>= 2.6.34, or a backport).
The option you need is
/proc/sys/net/ipv4/conf/*/proxy_arp_pvlan
:The upstream commit adding this support is 65324144b50bc7022cc9b6ca8f4a536a957019e3.
I am not sure the Linux proxyarp implementation can easily be tweaked to accomplish your goal. Have you considered using a subnetting/routing approach?
Here is the idea: Allocate, say, a
/24
address space for your wireless network. To match the example of your question, I'll use10.0.0.0/24
. Now carve up that/24
into 62/30
subnets:10.0.0.4/30
,10.0.0.8/30
,10.0.0.12/30
, ...10.0.0.248/30
.Each
/30
has 2 usable IP addresses, one of which is assigned to a wireless client, and the other is assigned (aliased) to theeth1
interface of your Linux router. To be concrete, let's say we assign wireless clients addresses from this series:10.0.0.6
,10.0.0.10
,10.0.0.14
, ...,10.0.0.250
. And we alias the following series of IPs toeth1
on the router:10.0.0.5
,10.0.0.9
,10.0.0.13
, ...,10.0.0.249
.To complete the configuration, each wireless client gets a netmask of
255.255.255.252
and a default gateway of10.0.0.X-1
(whereX
is the last octet of the client's IP address). On the router, theip
command can be used to add the IP addresses to eth1, as follows:Pros:
Cons: