How can I configure bidirectional protocol-independent port forwarding?
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I am attempting to solve the following problem:
I have a system which I will henceforth refer to as "Local" that hosts a service on port 80 and port 443, and depends on sending outgoing requests on port 25. It also hosts a separate service on port 22.
I have a system which I will call "Global" that has a globally accessible static IP address and has DNS configured for it, and is capable of accepting incoming requests on port 80, 443, 25, and 222.
Local and Global are connected (via a VPN interface, if it matters) on the reserved subnet 10.0.0.0/24
I want all incoming requests on Global ports 80 and 443 to redirect to Local on ports 80 and 443 respectively.
I also want incoming requests on Global port 222 to redirect to Local on port 22 (yes, that is an intentionally different port).
In addition, I want all outgoing requests to port 25 from Local to redirect to Global on port 25.
Both Local and Global are modern linux systems with apt, iptables, nftables, and ufw available.
I have tried a variety of iptables configurations with no success.
As far as I can tell a configuration that /should/ work (but doesn't!) is as follows:
Global:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward port 222 to Local:22
-A PREROUTING -p tcp --dport 222 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:22
# forward port 80 to Local:80
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:80
# forward port 443 to Local:443
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:443
# and forward the responses the other direction
-A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
COMMIT
Local:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward outgoing port 25 to Global:25
-A OUTPUT -p tcp --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 Subnet>:25
COMMIT
I realize that incoming requests for HTTP can be routed using nginx or apache configuration, but I want a generic solution that is not protocol-dependent and could be used for ssh or other protocols, as this traffic will not necessarily always be HTTP.
Does anyone know how this can be done?
Is there some reason that this type of configuration isn't possible?
networking iptables ufw nftables
add a comment |
I am attempting to solve the following problem:
I have a system which I will henceforth refer to as "Local" that hosts a service on port 80 and port 443, and depends on sending outgoing requests on port 25. It also hosts a separate service on port 22.
I have a system which I will call "Global" that has a globally accessible static IP address and has DNS configured for it, and is capable of accepting incoming requests on port 80, 443, 25, and 222.
Local and Global are connected (via a VPN interface, if it matters) on the reserved subnet 10.0.0.0/24
I want all incoming requests on Global ports 80 and 443 to redirect to Local on ports 80 and 443 respectively.
I also want incoming requests on Global port 222 to redirect to Local on port 22 (yes, that is an intentionally different port).
In addition, I want all outgoing requests to port 25 from Local to redirect to Global on port 25.
Both Local and Global are modern linux systems with apt, iptables, nftables, and ufw available.
I have tried a variety of iptables configurations with no success.
As far as I can tell a configuration that /should/ work (but doesn't!) is as follows:
Global:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward port 222 to Local:22
-A PREROUTING -p tcp --dport 222 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:22
# forward port 80 to Local:80
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:80
# forward port 443 to Local:443
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:443
# and forward the responses the other direction
-A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
COMMIT
Local:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward outgoing port 25 to Global:25
-A OUTPUT -p tcp --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 Subnet>:25
COMMIT
I realize that incoming requests for HTTP can be routed using nginx or apache configuration, but I want a generic solution that is not protocol-dependent and could be used for ssh or other protocols, as this traffic will not necessarily always be HTTP.
Does anyone know how this can be done?
Is there some reason that this type of configuration isn't possible?
networking iptables ufw nftables
Have you tried to use theFORWARD
chain on the default 'filter' table rather than doing the nat rules in thePREROUTING
chain? The masquerade rule looks right, the others might need to be changed.
– datUser
Mar 16 at 18:29
I tried setting it to use FORWARD but that didn't seem to work either. Interestingly however it does work with PREROUTING when I route to a different port on the same host, but it doesn't seem to forward to external hosts successfully.
– Dan
Mar 16 at 18:53
Yeah, so the PREROUTING chain is not for sending to other hosts, that would be FORWARD.
– datUser
Mar 16 at 21:35
add a comment |
I am attempting to solve the following problem:
I have a system which I will henceforth refer to as "Local" that hosts a service on port 80 and port 443, and depends on sending outgoing requests on port 25. It also hosts a separate service on port 22.
I have a system which I will call "Global" that has a globally accessible static IP address and has DNS configured for it, and is capable of accepting incoming requests on port 80, 443, 25, and 222.
Local and Global are connected (via a VPN interface, if it matters) on the reserved subnet 10.0.0.0/24
I want all incoming requests on Global ports 80 and 443 to redirect to Local on ports 80 and 443 respectively.
I also want incoming requests on Global port 222 to redirect to Local on port 22 (yes, that is an intentionally different port).
In addition, I want all outgoing requests to port 25 from Local to redirect to Global on port 25.
Both Local and Global are modern linux systems with apt, iptables, nftables, and ufw available.
I have tried a variety of iptables configurations with no success.
As far as I can tell a configuration that /should/ work (but doesn't!) is as follows:
Global:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward port 222 to Local:22
-A PREROUTING -p tcp --dport 222 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:22
# forward port 80 to Local:80
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:80
# forward port 443 to Local:443
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:443
# and forward the responses the other direction
-A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
COMMIT
Local:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward outgoing port 25 to Global:25
-A OUTPUT -p tcp --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 Subnet>:25
COMMIT
I realize that incoming requests for HTTP can be routed using nginx or apache configuration, but I want a generic solution that is not protocol-dependent and could be used for ssh or other protocols, as this traffic will not necessarily always be HTTP.
Does anyone know how this can be done?
Is there some reason that this type of configuration isn't possible?
networking iptables ufw nftables
I am attempting to solve the following problem:
I have a system which I will henceforth refer to as "Local" that hosts a service on port 80 and port 443, and depends on sending outgoing requests on port 25. It also hosts a separate service on port 22.
I have a system which I will call "Global" that has a globally accessible static IP address and has DNS configured for it, and is capable of accepting incoming requests on port 80, 443, 25, and 222.
Local and Global are connected (via a VPN interface, if it matters) on the reserved subnet 10.0.0.0/24
I want all incoming requests on Global ports 80 and 443 to redirect to Local on ports 80 and 443 respectively.
I also want incoming requests on Global port 222 to redirect to Local on port 22 (yes, that is an intentionally different port).
In addition, I want all outgoing requests to port 25 from Local to redirect to Global on port 25.
Both Local and Global are modern linux systems with apt, iptables, nftables, and ufw available.
I have tried a variety of iptables configurations with no success.
As far as I can tell a configuration that /should/ work (but doesn't!) is as follows:
Global:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward port 222 to Local:22
-A PREROUTING -p tcp --dport 222 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:22
# forward port 80 to Local:80
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:80
# forward port 443 to Local:443
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination <Local IP on 10.0.0.0/24 Subnet>:443
# and forward the responses the other direction
-A POSTROUTING -s 10.0.0.0/24 ! -d 10.0.0.0/24 -j MASQUERADE
COMMIT
Local:
/etc/ufw/before.rules (excerpt)
*nat
:PREROUTING ACCEPT [0:0]
# forward outgoing port 25 to Global:25
-A OUTPUT -p tcp --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 Subnet>:25
COMMIT
I realize that incoming requests for HTTP can be routed using nginx or apache configuration, but I want a generic solution that is not protocol-dependent and could be used for ssh or other protocols, as this traffic will not necessarily always be HTTP.
Does anyone know how this can be done?
Is there some reason that this type of configuration isn't possible?
networking iptables ufw nftables
networking iptables ufw nftables
edited Mar 24 at 15:49
Dan
asked Mar 16 at 18:04
DanDan
114
114
Have you tried to use theFORWARD
chain on the default 'filter' table rather than doing the nat rules in thePREROUTING
chain? The masquerade rule looks right, the others might need to be changed.
– datUser
Mar 16 at 18:29
I tried setting it to use FORWARD but that didn't seem to work either. Interestingly however it does work with PREROUTING when I route to a different port on the same host, but it doesn't seem to forward to external hosts successfully.
– Dan
Mar 16 at 18:53
Yeah, so the PREROUTING chain is not for sending to other hosts, that would be FORWARD.
– datUser
Mar 16 at 21:35
add a comment |
Have you tried to use theFORWARD
chain on the default 'filter' table rather than doing the nat rules in thePREROUTING
chain? The masquerade rule looks right, the others might need to be changed.
– datUser
Mar 16 at 18:29
I tried setting it to use FORWARD but that didn't seem to work either. Interestingly however it does work with PREROUTING when I route to a different port on the same host, but it doesn't seem to forward to external hosts successfully.
– Dan
Mar 16 at 18:53
Yeah, so the PREROUTING chain is not for sending to other hosts, that would be FORWARD.
– datUser
Mar 16 at 21:35
Have you tried to use the
FORWARD
chain on the default 'filter' table rather than doing the nat rules in the PREROUTING
chain? The masquerade rule looks right, the others might need to be changed.– datUser
Mar 16 at 18:29
Have you tried to use the
FORWARD
chain on the default 'filter' table rather than doing the nat rules in the PREROUTING
chain? The masquerade rule looks right, the others might need to be changed.– datUser
Mar 16 at 18:29
I tried setting it to use FORWARD but that didn't seem to work either. Interestingly however it does work with PREROUTING when I route to a different port on the same host, but it doesn't seem to forward to external hosts successfully.
– Dan
Mar 16 at 18:53
I tried setting it to use FORWARD but that didn't seem to work either. Interestingly however it does work with PREROUTING when I route to a different port on the same host, but it doesn't seem to forward to external hosts successfully.
– Dan
Mar 16 at 18:53
Yeah, so the PREROUTING chain is not for sending to other hosts, that would be FORWARD.
– datUser
Mar 16 at 21:35
Yeah, so the PREROUTING chain is not for sending to other hosts, that would be FORWARD.
– datUser
Mar 16 at 21:35
add a comment |
1 Answer
1
active
oldest
votes
Okay so after much consternation I was able to solve my original problem and can therefore post the correct solution here for anyone who might come across this in the future. Application layer configuration is outside the scope of the original question.
Firstly, if you have ufw set up you will need to allow these rules to apply without being blocked by the firewall. This will need to be done on BOTH hosts, if they both have ufw. This is done with the steps described at https://help.ubuntu.com/lts/serverguide/firewall.html under section heading "IP Masquerading", and they are summarized below
0) edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
1) edit /etc/ufw/sysctl.conf to set net/ipv4/ip_forward=1 and net/ipv6/conf/default/forwarding=1
2) put the desired iptables rules in /etc/ufw/before.rules using ufw's syntax, starting with *nat and ending with COMMIT
3) restart ufw
To redirect incoming packets, and proxy them through to Local, use the following configuration on Global:
#ensure forwarding is enabled, just for sanity's sake (for ufw sysctl.conf covers this)
sysctl -w net.ipv4.ip_forward=1
#rewrite incoming port 222 to Local:22
iptables -t nat -A PREROUTING -p tcp --dport 222 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:22
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Local:22
#rewriting the source means that the ACKs and other bidirectional data gets sent back to Global instead of attempting to go from Local directly to the originator
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 22 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
#repeat the above for ports 80 and 443, as in the original question
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:80
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 80 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:443
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 443 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
That covers the incoming proxy connection. For outgoing connections, we'll need the following configuration on Local:
#rewrite outgoing port 25 to Global:25, UNLESS it's meant for localhost (assumes lo is set up for ipv4, and not just ipv6)
iptables -t nat -A OUTPUT -p tcp '!' -d 127.0.0.1/32 --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 subnet>:25
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Global:25
iptables -t nat -A POSTROUTING -p tcp '!' -d 127.0.0.1/32 --dport 25 -j SNAT --to-source <Local IP on 10.0.0.0/24 subnet>
We needed to allow localhost so that it's possible to connect to a local server on that port, as that is how SMTP and many other programs (including DNS) that do proxying at the protocol level need to operate. Therefore we forwarded everything that wasn't bound for localhost.
That's it! That's the complete configuration at this level of the stack, and it will get your packets where they need to be. Application level configuration is outside the scope of this question.
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f506705%2fhow-can-i-configure-bidirectional-protocol-independent-port-forwarding%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Okay so after much consternation I was able to solve my original problem and can therefore post the correct solution here for anyone who might come across this in the future. Application layer configuration is outside the scope of the original question.
Firstly, if you have ufw set up you will need to allow these rules to apply without being blocked by the firewall. This will need to be done on BOTH hosts, if they both have ufw. This is done with the steps described at https://help.ubuntu.com/lts/serverguide/firewall.html under section heading "IP Masquerading", and they are summarized below
0) edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
1) edit /etc/ufw/sysctl.conf to set net/ipv4/ip_forward=1 and net/ipv6/conf/default/forwarding=1
2) put the desired iptables rules in /etc/ufw/before.rules using ufw's syntax, starting with *nat and ending with COMMIT
3) restart ufw
To redirect incoming packets, and proxy them through to Local, use the following configuration on Global:
#ensure forwarding is enabled, just for sanity's sake (for ufw sysctl.conf covers this)
sysctl -w net.ipv4.ip_forward=1
#rewrite incoming port 222 to Local:22
iptables -t nat -A PREROUTING -p tcp --dport 222 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:22
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Local:22
#rewriting the source means that the ACKs and other bidirectional data gets sent back to Global instead of attempting to go from Local directly to the originator
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 22 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
#repeat the above for ports 80 and 443, as in the original question
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:80
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 80 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:443
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 443 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
That covers the incoming proxy connection. For outgoing connections, we'll need the following configuration on Local:
#rewrite outgoing port 25 to Global:25, UNLESS it's meant for localhost (assumes lo is set up for ipv4, and not just ipv6)
iptables -t nat -A OUTPUT -p tcp '!' -d 127.0.0.1/32 --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 subnet>:25
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Global:25
iptables -t nat -A POSTROUTING -p tcp '!' -d 127.0.0.1/32 --dport 25 -j SNAT --to-source <Local IP on 10.0.0.0/24 subnet>
We needed to allow localhost so that it's possible to connect to a local server on that port, as that is how SMTP and many other programs (including DNS) that do proxying at the protocol level need to operate. Therefore we forwarded everything that wasn't bound for localhost.
That's it! That's the complete configuration at this level of the stack, and it will get your packets where they need to be. Application level configuration is outside the scope of this question.
add a comment |
Okay so after much consternation I was able to solve my original problem and can therefore post the correct solution here for anyone who might come across this in the future. Application layer configuration is outside the scope of the original question.
Firstly, if you have ufw set up you will need to allow these rules to apply without being blocked by the firewall. This will need to be done on BOTH hosts, if they both have ufw. This is done with the steps described at https://help.ubuntu.com/lts/serverguide/firewall.html under section heading "IP Masquerading", and they are summarized below
0) edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
1) edit /etc/ufw/sysctl.conf to set net/ipv4/ip_forward=1 and net/ipv6/conf/default/forwarding=1
2) put the desired iptables rules in /etc/ufw/before.rules using ufw's syntax, starting with *nat and ending with COMMIT
3) restart ufw
To redirect incoming packets, and proxy them through to Local, use the following configuration on Global:
#ensure forwarding is enabled, just for sanity's sake (for ufw sysctl.conf covers this)
sysctl -w net.ipv4.ip_forward=1
#rewrite incoming port 222 to Local:22
iptables -t nat -A PREROUTING -p tcp --dport 222 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:22
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Local:22
#rewriting the source means that the ACKs and other bidirectional data gets sent back to Global instead of attempting to go from Local directly to the originator
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 22 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
#repeat the above for ports 80 and 443, as in the original question
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:80
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 80 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:443
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 443 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
That covers the incoming proxy connection. For outgoing connections, we'll need the following configuration on Local:
#rewrite outgoing port 25 to Global:25, UNLESS it's meant for localhost (assumes lo is set up for ipv4, and not just ipv6)
iptables -t nat -A OUTPUT -p tcp '!' -d 127.0.0.1/32 --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 subnet>:25
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Global:25
iptables -t nat -A POSTROUTING -p tcp '!' -d 127.0.0.1/32 --dport 25 -j SNAT --to-source <Local IP on 10.0.0.0/24 subnet>
We needed to allow localhost so that it's possible to connect to a local server on that port, as that is how SMTP and many other programs (including DNS) that do proxying at the protocol level need to operate. Therefore we forwarded everything that wasn't bound for localhost.
That's it! That's the complete configuration at this level of the stack, and it will get your packets where they need to be. Application level configuration is outside the scope of this question.
add a comment |
Okay so after much consternation I was able to solve my original problem and can therefore post the correct solution here for anyone who might come across this in the future. Application layer configuration is outside the scope of the original question.
Firstly, if you have ufw set up you will need to allow these rules to apply without being blocked by the firewall. This will need to be done on BOTH hosts, if they both have ufw. This is done with the steps described at https://help.ubuntu.com/lts/serverguide/firewall.html under section heading "IP Masquerading", and they are summarized below
0) edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
1) edit /etc/ufw/sysctl.conf to set net/ipv4/ip_forward=1 and net/ipv6/conf/default/forwarding=1
2) put the desired iptables rules in /etc/ufw/before.rules using ufw's syntax, starting with *nat and ending with COMMIT
3) restart ufw
To redirect incoming packets, and proxy them through to Local, use the following configuration on Global:
#ensure forwarding is enabled, just for sanity's sake (for ufw sysctl.conf covers this)
sysctl -w net.ipv4.ip_forward=1
#rewrite incoming port 222 to Local:22
iptables -t nat -A PREROUTING -p tcp --dport 222 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:22
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Local:22
#rewriting the source means that the ACKs and other bidirectional data gets sent back to Global instead of attempting to go from Local directly to the originator
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 22 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
#repeat the above for ports 80 and 443, as in the original question
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:80
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 80 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:443
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 443 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
That covers the incoming proxy connection. For outgoing connections, we'll need the following configuration on Local:
#rewrite outgoing port 25 to Global:25, UNLESS it's meant for localhost (assumes lo is set up for ipv4, and not just ipv6)
iptables -t nat -A OUTPUT -p tcp '!' -d 127.0.0.1/32 --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 subnet>:25
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Global:25
iptables -t nat -A POSTROUTING -p tcp '!' -d 127.0.0.1/32 --dport 25 -j SNAT --to-source <Local IP on 10.0.0.0/24 subnet>
We needed to allow localhost so that it's possible to connect to a local server on that port, as that is how SMTP and many other programs (including DNS) that do proxying at the protocol level need to operate. Therefore we forwarded everything that wasn't bound for localhost.
That's it! That's the complete configuration at this level of the stack, and it will get your packets where they need to be. Application level configuration is outside the scope of this question.
Okay so after much consternation I was able to solve my original problem and can therefore post the correct solution here for anyone who might come across this in the future. Application layer configuration is outside the scope of the original question.
Firstly, if you have ufw set up you will need to allow these rules to apply without being blocked by the firewall. This will need to be done on BOTH hosts, if they both have ufw. This is done with the steps described at https://help.ubuntu.com/lts/serverguide/firewall.html under section heading "IP Masquerading", and they are summarized below
0) edit /etc/default/ufw to set DEFAULT_FORWARD_POLICY="ACCEPT"
1) edit /etc/ufw/sysctl.conf to set net/ipv4/ip_forward=1 and net/ipv6/conf/default/forwarding=1
2) put the desired iptables rules in /etc/ufw/before.rules using ufw's syntax, starting with *nat and ending with COMMIT
3) restart ufw
To redirect incoming packets, and proxy them through to Local, use the following configuration on Global:
#ensure forwarding is enabled, just for sanity's sake (for ufw sysctl.conf covers this)
sysctl -w net.ipv4.ip_forward=1
#rewrite incoming port 222 to Local:22
iptables -t nat -A PREROUTING -p tcp --dport 222 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:22
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Local:22
#rewriting the source means that the ACKs and other bidirectional data gets sent back to Global instead of attempting to go from Local directly to the originator
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 22 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
#repeat the above for ports 80 and 443, as in the original question
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:80
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 80 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-dest <Local IP on 10.0.0.0/24 subnet>:443
iptables -t nat -A POSTROUTING -d <Local IP on 10.0.0.0/24 subnet> -p tcp --dport 443 -j SNAT --to-source <Global IP on 10.0.0.0/24 subnet>
That covers the incoming proxy connection. For outgoing connections, we'll need the following configuration on Local:
#rewrite outgoing port 25 to Global:25, UNLESS it's meant for localhost (assumes lo is set up for ipv4, and not just ipv6)
iptables -t nat -A OUTPUT -p tcp '!' -d 127.0.0.1/32 --dport 25 -j DNAT --to-destination <Global IP on 10.0.0.0/24 subnet>:25
#having rewritten the destination, also rewrite the source for all packets that now have a destination of Global:25
iptables -t nat -A POSTROUTING -p tcp '!' -d 127.0.0.1/32 --dport 25 -j SNAT --to-source <Local IP on 10.0.0.0/24 subnet>
We needed to allow localhost so that it's possible to connect to a local server on that port, as that is how SMTP and many other programs (including DNS) that do proxying at the protocol level need to operate. Therefore we forwarded everything that wasn't bound for localhost.
That's it! That's the complete configuration at this level of the stack, and it will get your packets where they need to be. Application level configuration is outside the scope of this question.
answered Mar 24 at 15:46
DanDan
114
114
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f506705%2fhow-can-i-configure-bidirectional-protocol-independent-port-forwarding%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Have you tried to use the
FORWARD
chain on the default 'filter' table rather than doing the nat rules in thePREROUTING
chain? The masquerade rule looks right, the others might need to be changed.– datUser
Mar 16 at 18:29
I tried setting it to use FORWARD but that didn't seem to work either. Interestingly however it does work with PREROUTING when I route to a different port on the same host, but it doesn't seem to forward to external hosts successfully.
– Dan
Mar 16 at 18:53
Yeah, so the PREROUTING chain is not for sending to other hosts, that would be FORWARD.
– datUser
Mar 16 at 21:35