Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use iptables trough iptc, enables rootless operation #82

Merged
merged 1 commit into from
Jun 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions bin/opensnitch → opensnitch/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import warnings
import logging
import os
import sys

from opensnitch.version import VERSION
from opensnitch.snitch import Snitch
Expand All @@ -45,9 +44,6 @@

args = parser.parse_args()

if not os.geteuid() == 0:
sys.exit('OpenSnitch must be run as root.')


# Ensure Qt4 wont be loaded by matplotlib
try:
Expand Down
74 changes: 74 additions & 0 deletions opensnitch/iptables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import iptc


class IPTCRules:

def __init__(self):
self.tables = {
iptc.Table.FILTER: iptc.Table(iptc.Table.FILTER),
iptc.Table.MANGLE: iptc.Table(iptc.Table.MANGLE),
}
for t in self.tables.values():
t.autocommit = False

self.chains = {
c: r for c, r in (
self.insert_dns_rule(),
self.insert_connection_packet_rules(),
self.insert_reject_rule())
}

self.commit()

def commit(self):
for t in self.tables.values():
t.commit()
t.refresh()

def remove(self):
for c, r in self.chains.items():
c.delete_rule(r)

self.commit()

def insert_dns_rule(self):
"""Get DNS responses"""
chain = iptc.Chain(self.tables[iptc.Table.FILTER], 'INPUT')
rule = iptc.Rule()
rule.protocol = 'udp'
m = rule.create_match('udp')
m.sport = '53'

t = rule.create_target('NFQUEUE')
t.set_parameter('queue-num', str(0))
t.set_parameter('queue-bypass')

chain.insert_rule(rule)
return (chain, rule)

def insert_connection_packet_rules(self):
chain = iptc.Chain(self.tables[iptc.Table.MANGLE], 'OUTPUT')
rule = iptc.Rule()

t = rule.create_target('NFQUEUE')
t.set_parameter('queue-num', str(0))
t.set_parameter('queue-bypass')

m = rule.create_match('conntrack')
m.set_parameter('ctstate', 'NEW')

chain.insert_rule(rule)
return (chain, rule)

def insert_reject_rule(self):
chain = iptc.Chain(self.tables[iptc.Table.FILTER], 'OUTPUT')
rule = iptc.Rule()
rule.protol = 'tcp'

rule.create_target('REJECT')

m = rule.create_match('mark')
m.mark = '0x18ba5'

chain.insert_rule(rule)
return (chain, rule)
15 changes: 6 additions & 9 deletions opensnitch/snitch.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
import threading
import logging
import weakref
import os

from opensnitch.ui import QtApp
from opensnitch.connection import Connection
from opensnitch.dns import DNSCollector
from opensnitch.rule import RuleVerdict, Rules
from opensnitch.procmon import ProcMon
from opensnitch.iptables import IPTCRules


MARK_PACKET_DROP = 101285
Expand Down Expand Up @@ -103,19 +103,11 @@ def pkt_callback(self, pkt):
def run(self):
q = None
try:
for r in IPTABLES_RULES:
logging.debug("Applying iptables rule '%s'", r)
os.system("iptables -I %s" % r)

q = NetfilterQueue()
q.bind(0, self.pkt_callback, 1024 * 2)
q.run()

finally:
for r in IPTABLES_RULES:
logging.debug("Deleting iptables rule '%s'", r)
os.system("iptables -D %s" % r)

if q is not None:
q.unbind()

Expand Down Expand Up @@ -160,14 +152,19 @@ def __init__(self, database):
self.dns = DNSCollector()
self.q = NetfilterQueueWrapper(self)
self.procmon = ProcMon()
self.iptcrules = None
self.qt_app = QtApp(self.q.connection_futures, self.rules)

def start(self):
if ProcMon.is_ftrace_available():
self.procmon.enable()
self.procmon.start()

self.iptcrules = IPTCRules()
self.qt_app.run()

def stop(self):
if self.iptcrules is not None:
self.iptcrules.remove()

self.procmon.disable()
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@
'dpkt',
'NetfilterQueue',
'psutil',
'pyinotify'])
'pyinotify',
'python-iptables'
])