Skip to content

Commit eb0cee7

Browse files
committed
Add iptables FORWARD rule
1 parent e5c79ae commit eb0cee7

File tree

1 file changed

+76
-18
lines changed

1 file changed

+76
-18
lines changed

server/NatAndRoutingWrapper.h

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,48 @@
44
#include "libs/pcapplusplus/include/pcapplusplus/IpAddress.h"
55
#include <ostream>
66

7+
class IpTablesCommand {
8+
public:
9+
IpTablesCommand(const std::string &commandTemplate)
10+
: m_CommandTemplate(commandTemplate) {}
11+
12+
void run(bool enable) {
13+
std::string replacement = enable ? "-A" : "-D";
14+
std::string command = m_CommandTemplate;
15+
16+
auto pos = command.find(templateString);
17+
if (pos != std::string::npos) {
18+
command.replace(pos, templateString.length(), replacement);
19+
int result = std::system(command.c_str());
20+
if (result != 0) {
21+
throw std::runtime_error("Couldn't configure NAT: '" + command +
22+
"'");
23+
}
24+
25+
if (enable) {
26+
TOYVPN_LOG_DEBUG("Configured iptables: '" << command << "'");
27+
} else {
28+
TOYVPN_LOG_DEBUG("Disabled iptables: '" << command << "'");
29+
}
30+
31+
m_CommandRun = true;
32+
}
33+
}
34+
35+
void rollback() {
36+
if (m_CommandRun) {
37+
run(false);
38+
m_CommandRun = false;
39+
}
40+
}
41+
42+
constexpr static std::string_view templateString = "{enable}";
43+
44+
private:
45+
std::string m_CommandTemplate;
46+
bool m_CommandRun = false;
47+
};
48+
749
class NatAndRoutingWrapper {
850
public:
951
virtual ~NatAndRoutingWrapper() {
@@ -30,26 +72,42 @@ class NatAndRoutingWrapper {
3072
bool m_IsInitialized = false;
3173

3274
void configureNat(bool enable) {
33-
auto enableFlag = enable ? "-A" : "-D";
75+
std::ostringstream iptablesPostRoutingCommandStream;
76+
iptablesPostRoutingCommandStream
77+
<< "iptables -t nat " << IpTablesCommand::templateString
78+
<< " POSTROUTING -s " << m_PrivateNetwork.toString() << " -o "
79+
<< m_PublicNetworkInterface << " -j MASQUERADE";
80+
IpTablesCommand iptablesPostRoutingCommand(
81+
iptablesPostRoutingCommandStream.str());
3482

35-
std::ostringstream iptablesCommand;
36-
iptablesCommand << "iptables -t nat " << enableFlag
37-
<< " POSTROUTING -s " << m_PrivateNetwork.toString()
38-
<< " -o " << m_PublicNetworkInterface
39-
<< " -j MASQUERADE";
83+
std::ostringstream iptablesForwardCommandStream;
84+
iptablesForwardCommandStream
85+
<< "iptables"
86+
<< " " << IpTablesCommand::templateString << " FORWARD"
87+
<< " -i " << m_TunInterfaceName << " -o "
88+
<< m_PublicNetworkInterface << " -j ACCEPT";
89+
IpTablesCommand iptablesForwardCommand(
90+
iptablesForwardCommandStream.str());
4091

41-
int result = std::system(iptablesCommand.str().c_str());
42-
if (result != 0) {
43-
throw std::runtime_error("Couldn't configure NAT: '" +
44-
iptablesCommand.str() + "'");
45-
}
92+
std::ostringstream iptablesForwardCommandReverseStream;
93+
iptablesForwardCommandReverseStream
94+
<< "iptables"
95+
<< " " << IpTablesCommand::templateString << " FORWARD"
96+
<< " -i " << m_PublicNetworkInterface << " -o "
97+
<< m_TunInterfaceName << " -j ACCEPT";
98+
IpTablesCommand iptablesForwardCommandReverse(
99+
iptablesForwardCommandReverseStream.str());
100+
101+
try {
102+
iptablesPostRoutingCommand.run(enable);
103+
iptablesForwardCommand.run(enable);
104+
iptablesForwardCommandReverse.run(enable);
105+
} catch (const std::exception &) {
106+
iptablesPostRoutingCommand.rollback();
107+
iptablesForwardCommand.rollback();
108+
iptablesForwardCommandReverse.rollback();
46109

47-
if (enable) {
48-
TOYVPN_LOG_DEBUG("Configuring NAT: '" << iptablesCommand.str()
49-
<< "'");
50-
} else {
51-
TOYVPN_LOG_DEBUG("Disabling NAT: '" << iptablesCommand.str()
52-
<< "'");
110+
throw;
53111
}
54112
}
55113

@@ -64,4 +122,4 @@ class NatAndRoutingWrapper {
64122
ipRouteCommand.str() + "'");
65123
}
66124
}
67-
};
125+
};

0 commit comments

Comments
 (0)