Skip to content

Commit 46981a5

Browse files
committed
ISSUE-3 Allow to specify whether to add rule to the head or tail of the iptables chain
1 parent 80f432f commit 46981a5

8 files changed

Lines changed: 103 additions & 9 deletions

File tree

config/hostblock.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ iptables.rules.block = -s %i -j DROP
3636
## Or set up new iptables chain separate for hostblock
3737
#iptables.rules.block = -s %i -j HB_LOG_AND_DROP
3838

39+
## Whether to add iptables rule to the head or tail of the chain (default head)
40+
#iptables.rules.pos = head
41+
3942
## TODO Startup rules to check and add if they are missing
4043
## As example to automatically add HB_LOG_AND_DROP rules if host is restarted and rules are not restored with iptables-restore
4144
#iptables.rules.startup = -N HB_LOG_AND_DROP

hb/src/config.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,22 @@ bool Config::load()
153153
posip = line.find("%i");
154154
if (posip != std::string::npos) {
155155
this->iptablesRule = line;
156-
if (logDetails) this->log->debug("Iptables rule to drop packets: " + this->iptablesRule);
156+
if (logDetails) this->log->debug("Iptables rule to deny access: " + this->iptablesRule);
157157
} else {
158158
this->log->error("Failed to parse iptables.rules.block, IP address placeholder not found! Will use default value.");
159159
}
160160
}
161+
} else if (line.substr(0, 18) == "iptables.rules.pos") {
162+
pos = line.find_first_of("=");
163+
if (pos != std::string::npos) {
164+
line = hb::Util::toLower(hb::Util::ltrim(line.substr(pos + 1)));
165+
if (line == "tail") {
166+
this->iptablesAppend = true;
167+
} else {
168+
this->iptablesAppend = false;
169+
}
170+
if (logDetails) this->log->debug("Append iptables rule: " + std::to_string(this->iptablesAppend));
171+
}
161172
} else if (line.substr(0, 15) == "datetime.format") {
162173
pos = line.find_first_of("=");
163174
if (pos != std::string::npos) {
@@ -523,6 +534,8 @@ void Config::print()
523534
std::cout << "address.block.multiplier = " << this->keepBlockedScoreMultiplier << std::endl << std::endl;
524535
std::cout << "## Rule to use in IP tables rule (use %i as placeholder to specify IP address)" << std::endl;
525536
std::cout << "iptables.rules.block = " << this->iptablesRule << std::endl << std::endl;
537+
std::cout << "## Whether to add iptables rule to the head or end of the chain (default head)" << std::endl;
538+
std::cout << "iptables.rules.pos = " << (this->iptablesAppend ? "tail" : "head") << std::endl << std::endl;
526539
std::cout << "## Datetime format (default %Y-%m-%d %H:%M:%S)" << std::endl;
527540
std::cout << "datetime.format = " << this->dateTimeFormat << std::endl << std::endl;
528541
std::cout << "## Datafile location" << std::endl;

hb/src/config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ class Config{
3838
*/
3939
std::string iptablesRule = "-s %i -j DROP";
4040

41+
/*
42+
* Whether to append (add to the end) or insert (add to the beginning) iptables rule
43+
*/
44+
bool iptablesAppend = false;
45+
4146
/*
4247
* Datetime format
4348
*/

hb/src/data.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,8 +2000,14 @@ bool Data::updateIptables(std::string address)
20002000
if (createRule == true) {
20012001
this->log->info("Adding rule for " + address + " to iptables chain!");
20022002
try {
2003-
if (this->iptables->append("INPUT", ruleStart + address + ruleEnd) == false) {
2004-
this->log->error("Address " + address + " should have iptables rule, but hostblock failed to append rule to chain!");
2003+
bool res = false;
2004+
if (this->config->iptablesAppend) {
2005+
res = this->iptables->append("INPUT", ruleStart + address + ruleEnd);
2006+
} else {
2007+
res = this->iptables->insert("INPUT", ruleStart + address + ruleEnd, 1);
2008+
}
2009+
if (res == false) {
2010+
this->log->error("Address " + address + " should have iptables rule, but hostblock failed to add rule to chain!");
20052011
return false;
20062012
} else {
20072013
if (this->suspiciousAddresses.count(address) > 0) {
@@ -2014,7 +2020,7 @@ bool Data::updateIptables(std::string address)
20142020
} catch (std::runtime_error& e) {
20152021
std::string message = e.what();
20162022
this->log->error(message);
2017-
this->log->error("Address " + address + " should have iptables rule, but hostblock failed to append rule to chain!");
2023+
this->log->error("Address " + address + " should have iptables rule, but hostblock failed to add rule to chain!");
20182024
return false;
20192025
}
20202026
}

hb/src/iptables.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ bool Iptables::newChain(std::string chain)
6363
}
6464

6565
/*
66-
* Append rule to chain
66+
* Append rule to the end of the chain
6767
*/
6868
bool Iptables::append(std::string chain, std::string rule)
6969
{
@@ -91,7 +91,7 @@ bool Iptables::append(std::string chain, std::string rule)
9191
}
9292

9393
/*
94-
* Append rules to chain
94+
* Append multiple rules to the end of the chain
9595
*/
9696
bool Iptables::append(std::string chain, std::vector<std::string>* rules)
9797
{
@@ -117,6 +117,61 @@ bool Iptables::append(std::string chain, std::vector<std::string>* rules)
117117
return true;
118118
}
119119

120+
/*
121+
* Insert rule to the chain at specified position
122+
*/
123+
bool Iptables::insert(std::string chain, std::string rule, int pos)
124+
{
125+
// Need root access to work with iptables
126+
if (cunistd::getuid() != 0) {
127+
throw std::runtime_error("Error, root access required to work with iptables!");
128+
}
129+
130+
// Prepare command
131+
std::string cmd = "iptables -I " + chain + " " + std::to_string(pos) + " " + rule;
132+
int response = 0;
133+
if (!std::system(NULL)) {
134+
throw std::runtime_error("Command processor not available.");
135+
}
136+
137+
// Exec command
138+
response = std::system(cmd.c_str());
139+
140+
// Check response
141+
if (response == 0) {
142+
return true;
143+
} else {
144+
throw std::runtime_error("Failed to execute iptables, returned code: " + std::to_string(response));
145+
}
146+
}
147+
148+
/*
149+
* Append multiple rules at specified position in chain
150+
*/
151+
bool Iptables::insert(std::string chain, std::vector<std::string>* rules, int pos)
152+
{
153+
// Need root access to work with iptables
154+
if (cunistd::getuid() != 0) {
155+
throw std::runtime_error("Error, root access required to work with iptables!");
156+
}
157+
158+
int response = 0;
159+
if (!std::system(NULL)) {
160+
throw std::runtime_error("Command processor not available.");
161+
}
162+
163+
std::string cmd;
164+
for (std::vector<std::string>::iterator it = rules->begin(); it != rules->end(); ++it) {
165+
cmd = "iptables -I " + chain + " " + std::to_string(pos) + " " + *it;
166+
response = std::system(cmd.c_str());
167+
if (response != 0) {
168+
throw std::runtime_error("Failed to execute iptables, returned code: " + std::to_string(response));
169+
}
170+
}
171+
172+
return true;
173+
}
174+
120175
/*
121176
* Delete rule from chain
122177
*/

hb/src/iptables.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,17 @@ class Iptables{
2828
bool newChain(std::string chain);
2929

3030
/*
31-
* Append chain with new rule
31+
* Append new rule(s) to the end of the chain
3232
*/
3333
bool append(std::string chain, std::string rule);
3434
bool append(std::string chain, std::vector<std::string>* rules);
3535

36+
/*
37+
* Insert rule(s) to the chain at specified position
38+
*/
39+
bool insert(std::string chain, std::string rule, int pos = 1);
40+
bool insert(std::string chain, std::vector<std::string>* rules, int pos = 1);
41+
3642
/*
3743
* Delete rule from chain
3844
*/

hb/src/main.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,13 @@ int main(int argc, char *argv[])
879879

880880
// Add rule based on new config
881881
try {
882-
if (iptables.append("INPUT", config.iptablesRule.substr(0, posip) + regexSearchResult + config.iptablesRule.substr(posip + 2)) == false) {
882+
bool res = false;
883+
if (config.iptablesAppend) {
884+
res = iptables.append("INPUT", config.iptablesRule.substr(0, posip) + regexSearchResult + config.iptablesRule.substr(posip + 2));
885+
} else {
886+
res = iptables.insert("INPUT", config.iptablesRule.substr(0, posip) + regexSearchResult + config.iptablesRule.substr(posip + 2), 1);
887+
}
888+
if (res == false) {
883889
log.error("Trying to update rule for address " + regexSearchResult + " based on updated configuraiton, but failed to add rule based on new configuration!");
884890
} else {
885891
sait->second.iptableRule = true;

hb/src/util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace hb{
1414

15-
static const std::string kHostblockVersion = "1.0.2";
15+
static const std::string kHostblockVersion = "1.0.3";
1616

1717
enum Report {
1818
False,

0 commit comments

Comments
 (0)