Browse Source

Control Panel fixes & whole domain blocks

* Fix config files and init script
 * Help text and error coloring in WUI template.
 * EOL white space. :-/
 * Add whole domain blocking
master
Jon Foster 3 months ago
parent
commit
bb0278f2a5
8 changed files with 157 additions and 63 deletions
  1. +12
    -0
      controlpanel/TODO.md
  2. +1
    -0
      controlpanel/data.h
  3. +1
    -0
      controlpanel/default
  4. +18
    -11
      controlpanel/init
  5. +3
    -3
      controlpanel/lighttpd.conf
  6. +13
    -3
      controlpanel/mainskin.tmpl
  7. +2
    -2
      controlpanel/sample.js
  8. +107
    -44
      controlpanel/trafficctrl.cpp

+ 12
- 0
controlpanel/TODO.md View File

@@ -0,0 +1,12 @@

* Add comments to "dns" decision table
* "dns.decided" field should default to the last hit in "connections".
* format table centered with the title.
* Extend DNS mechanism to incorporate anonymous (no DNS) connections.
* Daemonization mechanism to allow us to run as non-root.
* C++CMS creates socket as original user:group (typically root:root). Yet the
PID file is written as the requested user:group. This means that permissions
on the socket have to be handled outside of C++CMS or it needs some patchery.
* Tool to read JSON conf and supply values to "init" script.
* Some list filtering tools in the WUI to target actions on specific subsets
of DNS names

+ 1
- 0
controlpanel/data.h View File

@@ -28,6 +28,7 @@ struct Domain {
struct DomainList :public cppcms::base_content {
std::vector<Domain> list;
std::string filter; // Which filter was used to show list
std::string error;
int page, pages, page_size, count;
};



+ 1
- 0
controlpanel/default View File

@@ -2,6 +2,7 @@
# defaults.

# Configuration file for the TrafficCtrl server
# NOTE: service won't start until this is set
#CONF=/etc/poorman-ids/sample.js
# Where "run" files are placed. This is the Debian+ default:
#RUN=/run


+ 18
- 11
controlpanel/init View File

@@ -16,7 +16,7 @@
NAME="trafficctrl"
DAEMON="/usr/sbin/$NAME"
RUN=/run
CONF=/etc/poorman-ids/sample.js
CONF=""
PID=""
GROUP=""

@@ -49,11 +49,16 @@ CTRL() {

do_start() {
echo -n "Starting Traffic Control: "
if [ -z "$CONF" ]; then
echo "NOT CONFIGURED"
return 0
fi
if CTRL --start --oknodo --umask 007 $GROUP -- -c "$CONF"; then
echo "OK"
return 0 #JIC
else
echo "FAIL"
exit 1
return 1
fi
}

@@ -63,9 +68,10 @@ do_stop() {
echo -n "Stoping Traffic Control: "
if CTRL --stop --remove-pidfile; then
echo "OK"
return 0 #JIC
else
echo "FAIL"
exit 1
return 1
fi
}

@@ -75,36 +81,37 @@ do_status() {
echo -n "Traffic Control is: "
if CTRL --status; then
echo "Up"
return 0 #JIC
else
echo "Down"
exit 1
return 1
fi
}



### Main()
### Main()

case "$1" in
start)
do_start
;;
stop)
do_stop
;;
restart)
do_status && do_stop
do_start
;;
status)
do_status
;;
*)
echo "$0 {start | stop | restart | status}"
;;
esac
esac

+ 3
- 3
controlpanel/lighttpd.conf View File

@@ -5,11 +5,11 @@
#fastcgi.debug = 1
fastcgi.server = (
"/webmonitor" =>
( "trafficctrl" =>
( "trafficctrl" =>
( "socket" => "/run/poorman-ids/trafficctrl.fcgi",
"check-local" => "disable",
# "fix-root-scriptname" => "enable",
#"docroot" => "/" # remote server may use
#"docroot" => "/" # remote server may use
# its own docroot

)
@@ -20,7 +20,7 @@ fastcgi.server = (

auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/etc/lighttpd/lighttpd.users"
auth.require += ( "/webmonitor" => (
auth.require += ( "/webmonitor" => (
"method" => "basic",
"realm" => "Web Monitor",
#"require" => "user=root"


+ 13
- 3
controlpanel/mainskin.tmpl View File

@@ -52,21 +52,31 @@
border-top: 2px solid black;
border-bottom: 2px solid black;
padding: 0.25em;
}
}
div.pager {
font-weight: bold;
}
</style>
</head><body>
<div class="menu"><% include menu() %></div>
<h1><% include title() %></h1>
<div id="content">
<% foreach domain rowid r from 1 in list %>
<% include pager(page, pages) %>
<% if not empty error %>
<p style="color: red"><i><b><%= error %></b></i></p>
<% end %>
<form method="POST">
Whole Domain: <input name="domain" size=50>
<p><i><b>NOTE:</b> the root domain name listed here will match any records in
this list with the same suffix and record the decision as chosen below.
<% if ( content.filter == "undecided" ) %>
Whole domains can be blocked by prefixing them with "*.". This means that
even if the exact host name or subdomain is not listed here it will get
blocked.
<% end %>
<table>
<tr><th><select name="op" value="0">
<option value="0">Undecided</option>


+ 2
- 2
controlpanel/sample.js View File

@@ -34,7 +34,7 @@
// // or "socket": "path..."
// },
// "http" : { "script": "" },
// This is a FastCGI example, which could be used to provide HTTPS & passwords
// via the host service:
"service": {
@@ -42,7 +42,7 @@
// To serve on a TCP socket: "ip": "0.0.0.0", "port": 8080
// or a socket. preferred if lesser privlieged users have access
// to the server:
"socket": "/run/poorman-ids/traffcctl.fcgi
"socket": "/run/poorman-ids/traffcctl.fcgi"
},

// In context of restricted access environment this is probably OK.


+ 107
- 44
controlpanel/trafficctrl.cpp View File

@@ -5,8 +5,10 @@
// Copyright JF Possibilities, Inc. All rights reserved.
//
// Provide a control panel to manage which domains we want to watch,
// ignore anc block.
// ignore and block.
//////////////////////////////////////////////////////////////////////
// TODO: put the note fields to use (dns,dns_wild)
// TODO: Any purpose in wild-card selection "accepted" host names?
#include <stdlib.h>
#include <string>
#include <stdexcept>
@@ -36,6 +38,21 @@


//////////////////////////////////////////////////////////////////////
// DNS wild card matcher
//////////////////////////////////////////////////////////////////////

bool dns_wild_match(const StringList &wilds, const std::string &host) {
for(StringList::const_iterator i=wilds.begin(); i!=wilds.end(); i++) {
if(host.length()<i->length()) continue;
if(host==*i) return true;
if(host.substr(host.length()-i->length()+1)=="."+*i) return true;
}
return false;
}



//////////////////////////////////////////////////////////////////////
// C++CMS App to manage the state of all known domain names.
//////////////////////////////////////////////////////////////////////

@@ -48,7 +65,7 @@ struct app: public cppcms::application {
int items_per_page;


std::string numlist(const std::string &field) {
std::string r;
const cppcms::http::request::form_type &POST = request().post();
@@ -64,19 +81,66 @@ struct app: public cppcms::application {
}
return r;
}
void list(Domain::STATUS sid) {
int i;



/// This looks at new log entries and creates missing DNS entries.
/// This should be run periodically. Right now we run just prior
/// displaying a "list" page. This could be used in a CRON job...

void catchup() {
std::string s;
StringList list;
DomainList c;
StringList wild;

/// Read list of wild-card blocks ///

cppdb::result r = *sql
<< "SELECT name FROM dns_wild WHERE status=?"
<< Domain::blocked;
while(r.next()) {
r >> s;
wild.push_back(s);
}


/// Auto-add unknown domains to DNS list ///

// Find all connections not recorded in the DNS table
r = *sql <<
"SELECT c.them_name "
"FROM connections c LEFT OUTER JOIN dns ON c.them_name=dns.name "
"WHERE c.them_name<>'' AND dns.name IS NULL "
"GROUP BY c.them_name";
while(r.next()) {
r >> s;
list.push_back(s);
}

// add them
if(!list.empty()) {
cppdb::statement q = *sql << "INSERT INTO dns (name, status) VALUES (?,?)";
for(StringList::iterator i=list.begin(); i!=list.end(); i++) {
q.reset();
// If blocked by wild card add it to the blocked list otherwise its
// undecided.
q << *i << (Domain::blocked*dns_wild_match(wild, *i)) << cppdb::exec;
}
}
}



void list(Domain::STATUS sid) {
int i;
std::string s;
DomainList c;
cppdb::result r;

// TODO: put this someplace else?
/// Form processing ///
if(request().request_method()=="POST") {
std::string op = request().post("op");
// nothing to do without a valid "op"
@@ -86,37 +150,36 @@ struct app: public cppcms::application {
*sql << "UPDATE dns SET status="+op+" WHERE name IN ("+s+")"
<< cppdb::exec;
}
if((s=request().post("domain"))!="") {
if(s=="*" || s=="*.") {
c.error = "'*' and '*.' are not acceptable.";
} else if((s=request().post("domain"))!="") {
// wild card block handling
if(s.substr(0,2)=="*.") {
s = s.substr(2);
if(op=="2")
*sql << "INSERT INTO dns_wild (name,status) VALUES (?,?)"
<< s << op
<< cppdb::exec;
else
c.error = "Wild cards can only be used to <b>block</b> domains. "
"This has been treated as regular domain prefix "
"search.";
}
// regardless move all existing matches to the specified status.
*sql << "UPDATE dns SET status=? WHERE name=? OR name LIKE ?"
<< op << s << ("%."+s)
<< cppdb::exec;
}
}
}
/// Auto add unknown domains to DNS list ///

cppdb::result r = *sql <<
"SELECT c.them_name "
"FROM connections c LEFT OUTER JOIN dns ON c.them_name=dns.name "
"WHERE c.them_name<>'' AND dns.name IS NULL "
"GROUP BY c.them_name";
while(r.next()) {
r >> s;
list.push_back(s);
}
if(!list.empty()) {
cppdb::statement q = *sql << "INSERT INTO dns (name) VALUES (?)";
for(StringList::iterator i=list.begin(); i!=list.end(); i++) {
q.reset();
q << *i << cppdb::exec;
}
}
/// Produce list of unknowns ///
c.filter = filter_titles[sid];
/// Update DB with new log data ///

catchup();

/// Produce list of names of the desired STATUS ///

c.filter = filter_titles[sid];
s = request().get("pg");
if(s=="")
c.page = 1;
@@ -136,22 +199,22 @@ struct app: public cppcms::application {
c.pages = (c.count+items_per_page-1)/items_per_page;
render("mainskin", "domain_list", c);
}
void undecided() { list(Domain::undecided); }
void accepted() { list(Domain::accepted ); }
void blocked() { list(Domain::blocked ); }
app(cppcms::service &s): cppcms::application(s), items_per_page(50) {
#ifdef DEBUGGIN
std::cerr << "spawning app object" << std::endl;
#endif
sql.reset(new cppdb::session());
sql->open(settings().get<std::string>("trafficctrl.db"));
mapper().root(root_uri);
mapper().assign("blocked", "/blocked");
dispatcher().assign("/blocked/?", &app::blocked, this);
@@ -161,7 +224,7 @@ std::cerr << "spawning app object" << std::endl;
dispatcher().assign("/?", &app::undecided, this);

}
// logging
void main(const std::string url) {
#ifdef DEBUGGIN
@@ -172,7 +235,7 @@ std::cerr << "request: " << url << '\n'
#endif
cppcms::application::main(url);
}
};




Loading…
Cancel
Save