Eu encontrei uma solução:
external
interfaces: eth0
masquerade: yes
internal
interfaces: tun0
masquerade: no
public (default)
interfaces: # not used
masquerade: no
trusted
interfaces: lo
masquerade: no
Para que isso funcionasse, eu tive que declarar explicitamente que lo estava na trusted zone, tun0 estava na internal zone e eth0 estava na external zone. Para fazer isso, eu usei (por exemplo):
firewall-cmd --permanent --zone=external --add-interface=eth0
firewall-cmd --permanent --zone=internal --add-interface=tun0
firewall-cmd --permanent --zone=trusted --add-interface=lo
firewall-cmd --reload
Para eth0 , também foi necessário adicionar ZONE="external" a /etc/sysconfig/network-scripts/ifcfg-eth0 para continuar trabalhando nas reinicializações. Isso não foi necessário para as outras interfaces.
Os serviços / portas reais abrem na zona trusted e internal , deixei seus padrões. Certifiquei-me de que a zona padrão ( public ) tinha ssh (que é o padrão) para emergências (como se uma atualização renomeie a interface eth0 ) e adicionei os serviços que desejo expor à external zone. / p>
masquerade já estava ativado por padrão na zona external e desativado nas outras.
Esta configuração funciona com firewalld-0.3.9-14.el7.noarch
Eu não tenho certeza porque colocá-los em zonas separadas era necessário para excluir a interface de loopback do masquerading (transformando o mascaramento em sets da regra: -A POST_external_allow ! -i lo -j MASQUERADE , o que parece suficiente para mim, mas eu não sou especialista). No entanto, eu achei este bug que pode estar relacionado e o problema pode ser corrigido em versões futuras.