Is it possible to use proxy-arp back to the same interface?
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
:
proxy_arp_pvlan - BOOLEAN Private VLAN proxy arp. Basically allow proxy arp replies back to the same interface (from which the ARP request/solicitation was received). This is done to support (ethernet) switch features, like RFC 3069, where the individual ports are NOT allowed to communicate with each other, but they are allowed to talk to the upstream router. As described in RFC 3069, it is possible to allow these hosts to communicate through the upstream router by proxy_arp'ing. Don't need to be used together with proxy_arp. This technology is known by different names: In RFC 3069 it is called VLAN Aggregation. Cisco and Allied Telesyn call it Private VLAN. Hewlett-Packard call it Source-Port filtering or port-isolation. Ericsson call it MAC-Forced Forwarding (RFC Draft).
The upstream commit adding this support is 65324144b50bc7022cc9b6ca8f4a536a957019e3.