Я пытался сделать что-то подобное. Пройдя через несколько учебных пособий, которые, казалось, никогда не работали, пока я не подключил Wiresharked к соединению, чтобы обнаружить, что адрес назначения все еще был установлен на внешний IP-адрес (точно так же, как вы описали), я попытался использовать цепочку POSTROUTING, чтобы изменить IP-адрес источника для сервера:
iptables -t nat -A POSTROUTING -p <tcp/udp> --dport <destination_port> -j SNAT --to <$PUBLICHOST_INTERNAL_IP>
После того, как я добавил это правило, соединение было перенаправлено в частную сеть, и ответные пакеты возвращались по тому же пути к клиенту, а не через сетевой шлюз. Я не уверен, что позволило ответным пакетам возвращаться через сервер брандмауэра, но я думаю, что это было из-за правила, которое я уже имел в цепочке INPUT, чтобы разрешить установленные соединения:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
С этим решением следует иметь в виду следующее: если вы когда-нибудь измените внутренний IP-адрес сервера брандмауэра, вам потребуется обновить указанное выше правило POSTROUTING. (Излишне говорить, что, вероятно, лучше всего, если сервер брандмауэра имеет статически назначенный внутренний IP-адрес).