Você pode postar a saída de ip main show table route e ip route show table 200 ? Eu suspeito que você está perdendo algumas rotas na sua mesa '200'. Sua tabela de rota '200' deve ter praticamente as mesmas rotas que a tabela 'main', sendo a única diferença a rota padrão.
Eu vejo que você atualizou e acredito que minha sugestão original estava correta. Observe como sua tabela principal tem a rota 'link de escopo' para sua rede local e o link vpn? Essas rotas também devem ser adicionadas à tabela '200'.
Tente executar esses comandos além dos outros comandos que você usa.
ip route add 192.168.2.0/24 dev tap0 proto kernel scope link src 192.168.2.4 table 200
ip route add 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.101 metric 2 table 200
ip route flush cache
Se você quiser criar scripts para a criação dessas rotas, você pode usar isso. Ele copiará todas as rotas de 'link de escopo' da tabela de rotas principal para sua outra tabela.
#!/bin/bash
IFACE=wlan0
RT=200
/sbin/ip route list scope link table main proto kernel dev ${IFACE} \
| while read ROUTE ; do
# and add that route to all the tables mentioned in the rrtables option
# in the interfaces file
/sbin/ip route add table ${RT} scope link proto kernel dev ${IFACE} ${ROUTE}
done
Outra atualização. Acabei de notar que perdi algo bastante óbvio antes.
Sua instrução MASQ parece estar funcionando na eth0. Nas tabelas de rotas que você postou, seu dispositivo de saída não é eth0. Em vez disso.
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
Você provavelmente deve usar apenas uma declaração como essa.
iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE