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+
749class 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