renaming things for distutils

This commit is contained in:
kayos 2020-08-09 01:10:55 -07:00
parent 2a8fb43dd5
commit 4e9dbe6e92
23 changed files with 84 additions and 82 deletions

30
README

@ -52,26 +52,26 @@ Some History:
cryptography to /simplify/ the initial port knocking concept,
rather than making it more complex.
knockknock Overview:
knocknock Overview:
So here's how knockknock works:
So here's how knocknock works:
* Servers run the python app 'knockknock-daemon', and clients
* Servers run the python app 'knocknock-daemon', and clients
open ports on those servers by running the python app
'knockknock'
'knocknock'
* 'knockknock-daemon' simply tails kern.log. It doesn't bind to
* 'knocknock-daemon' simply tails kern.log. It doesn't bind to
any sockets, load libpcap and inspect every packet, or send
anything onto the network at all.
* When you want to open a port from a client, you run
'knockknock', which sends a /single/ SYN packet to the server.
'knocknock', which sends a /single/ SYN packet to the server.
The packet's IP and TCP headers are encoded to represent an
IND-CCA secure encrypted request to open a specified port from
the source IP address.
* Fields from this packet are logged to kern.log and processed
by 'knockknock-daemon', which validates them.
by 'knocknock-daemon', which validates them.
* You connect from the client to the now-open port on the
server.
@ -87,26 +87,26 @@ knockknock Overview:
evesdropping, replay attacks, and all known forms of cryptanalysis
against IND-CCA secure schemes.
Why Is knockknock Secure?
Why Is knocknock Secure?
* The knockknock-daemon code is very simple, and is written in
* The knocknock-daemon code is very simple, and is written in
python (a 'safe' language). The code is concise enough to be
easily audited, and doesn't make use of any crazy libraries like
libpcap.
* While knockknock-daemon needs root priviledges to adjust
* While knocknock-daemon needs root priviledges to adjust
iptables rules, it employs privilege separation to isolate the
code that actually runs as root to ~15 lines. So even though
the entire code base is very small and very simple, the only
part of the code actually running with root privilges is even
smaller and even simpler. When you run knockknock-daemon, it
smaller and even simpler. When you run knocknock-daemon, it
will fork out the privileged code and drop privilges everywhere
else before processing knockknock requests.
else before processing knocknock requests.
* The communication protocol is a simple IND-CCA secure encryption
scheme that uses standard, contemporary, cryptographic
constructions. An observer watching packets is not given any
indication that the SYN packet transmitted by 'knockknock' is a
indication that the SYN packet transmitted by 'knocknock' is a
port knocking request, but even if they knew, there would be no
way for them to determine which port was requested to open.
Replaying the knock request later does them no good, and in fact
@ -131,9 +131,9 @@ Why Is This Even Necessary?
have?
The name of the game is to isolate, compartmentalize, and /expose
running services as little as possible/. That's where knockknock
running services as little as possible/. That's where knocknock
comes in. Given that your network services are insecure, you want
to expose as few of them to the world as possible. I offer
knockknock as a possible solution to minimizing exposure.
knocknock as a possible solution to minimizing exposure.

@ -1,5 +1,5 @@
#!/usr/bin/env python
"""knockknock-daemon implements Moxie Marlinspike's port knocking protocol."""
"""knocknock3-daemon implements Moxie Marlinspike's port knocking protocol."""
__author__ = "Moxie Marlinspike"
__email__ = "moxie@thoughtcrime.org"
@ -25,27 +25,27 @@ USA
import os, sys, pwd, grp
from knockknock.LogEntry import LogEntry
from knockknock.LogFile import LogFile
from knockknock.Profiles import Profiles
from knockknock.PortOpener import PortOpener
from knockknock.DaemonConfiguration import DaemonConfiguration
from knockknock.KnockWatcher import KnockWatcher
from knocknock3.LogEntry import LogEntry
from knocknock3.LogFile import LogFile
from knocknock3.Profiles import Profiles
from knocknock3.PortOpener import PortOpener
from knocknock3.DaemonConfiguration import DaemonConfiguration
from knocknock3.KnockWatcher import KnockWatcher
import knockknock.daemonize
import knocknock3.daemonize
def checkPrivileges():
if (not os.geteuid() == 0):
print("Sorry, you have to run knockknock-daemon as root.")
print("Sorry, you have to run knocknock3-daemon as root.")
sys.exit(3)
def checkConfiguration():
if (not os.path.isdir('/etc/knockknock.d/')):
print("/etc/knockknock.d/ does not exist. You need to setup your profiles first..")
if (not os.path.isdir('/etc/knocknock3.d/')):
print("/etc/knocknock3.d/ does not exist. You need to setup your profiles first..")
sys.exit(3)
if (not os.path.isdir('/etc/knockknock.d/profiles/')):
print("/etc/knockknock.d/profiles/ does not exist. You need to setup your profiles first...")
if (not os.path.isdir('/etc/knocknock3.d/profiles/')):
print("/etc/knocknock3.d/profiles/ does not exist. You need to setup your profiles first...")
sys.exit(3)
def dropPrivileges():
@ -73,13 +73,13 @@ def main(argv):
checkPrivileges()
checkConfiguration()
profiles = Profiles('/etc/knockknock.d/profiles/')
config = DaemonConfiguration('/etc/knockknock.d/config')
profiles = Profiles('/etc/knocknock3.d/profiles/')
config = DaemonConfiguration('/etc/knocknock3.d/config')
if (profiles.isEmpty()):
print('WARNING: Running knockknock-daemon without any active profiles.')
print('WARNING: Running knocknock3-daemon without any active profiles.')
knockknock.daemonize.createDaemon()
knocknock3.daemonize.createDaemon()
input, output = os.pipe()
pid = os.fork()

@ -23,14 +23,14 @@ USA
"""
import os, sys
from knockknock.Profiles import Profiles
from knockknock.Profile import Profile
from knocknock3.Profiles import Profiles
from knocknock3.Profile import Profile
DAEMON_DIR = '/etc/knockknock.d/'
DAEMON_DIR = '/etc/knocknock3.d/'
PROFILES_DIR = DAEMON_DIR + 'profiles/'
def usage():
print("knockknock-genprofile <profileName> <knockPort>")
print("knocknock3-genprofile <profileName> <knockPort>")
sys.exit(3)
def checkProfile(profileName):

@ -24,10 +24,10 @@ USA
import os, sys, asyncore, socket
from knockknock.Profiles import Profiles
from knockknock.proxy.SocksRequestHandler import SocksRequestHandler
from knocknock3.Profiles import Profiles
from knocknock3.proxy.SocksRequestHandler import SocksRequestHandler
import knockknock.daemonize
import knocknock3.daemonize
class ProxyServer(asyncore.dispatcher):
@ -45,26 +45,26 @@ class ProxyServer(asyncore.dispatcher):
def usage():
print("knockknock-proxy <listenPort>")
print("knocknock3-proxy <listenPort>")
sys.exit(3)
def getProfiles():
homedir = os.path.expanduser('~')
profiles = Profiles(homedir + '/.knockknock/')
profiles = Profiles(homedir + '/.knocknock3/')
profiles.resolveNames()
return profiles
def checkPrivileges():
if not os.geteuid() == 0:
print("\nSorry, knockknock-proxy has to be run as root.\n")
print("\nSorry, knocknock3-proxy has to be run as root.\n")
usage()
def checkProfiles():
homedir = os.path.expanduser('~')
if not os.path.isdir(homedir + '/.knockknock/'):
print("Error: you need to setup your profiles in " + homedir + "/.knockknock/")
if not os.path.isdir(homedir + '/.knocknock3/'):
print("Error: you need to setup your profiles in " + homedir + "/.knocknock3/")
sys.exit(2)
def main(argv):
@ -78,7 +78,7 @@ def main(argv):
profiles = getProfiles()
server = ProxyServer(int(argv[0]), profiles)
knockknock.daemonize.createDaemon()
knocknock3.daemonize.createDaemon()
asyncore.loop(use_poll=True)

@ -26,10 +26,10 @@ import getopt
import subprocess
from struct import *
from knockknock.Profile import Profile
from knocknock3.Profile import Profile
def usage():
print("Usage: knockknock.py -p <portToOpen> <host>")
print("Usage: knocknock3.py -p <portToOpen> <host>")
sys.exit(2)
def parseArguments(argv):
@ -60,15 +60,15 @@ def parseArguments(argv):
def getProfile(host):
homedir = os.path.expanduser('~')
if not os.path.isdir(homedir + '/.knockknock/'):
print("Error: you need to setup your profiles in " + homedir + '/.knockknock/')
if not os.path.isdir(homedir + '/.knocknock3/'):
print("Error: you need to setup your profiles in " + homedir + '/.knocknock3/')
sys.exit(2)
if not os.path.isdir(homedir + '/.knockknock/' + host):
print('Error: profile for host ' + host + ' not found at ' + homedir + '/.knockknock/' + host)
if not os.path.isdir(homedir + '/.knocknock3/' + host):
print('Error: profile for host ' + host + ' not found at ' + homedir + '/.knocknock3/' + host)
sys.exit(2)
return Profile(homedir + '/.knockknock/' + host)
return Profile(homedir + '/.knocknock3/' + host)
def verifyPermissions():
if os.getuid() != 0:

@ -29,7 +29,7 @@ class DaemonConfiguration:
self.delay = int(parser.get('main', 'delay'))
self.window = int(parser.get('main', 'error_window'))
except ConfigParser.NoSectionError:
print("knockknock-daemon: config file not found, assuming defaults.")
print("knocknock3-daemon: config file not found, assuming defaults.")
self.delay = 15
self.window = 20

@ -33,7 +33,7 @@ class PortOpener:
port = self.stream.readline().rstrip("\n")
if sourceIP == "" or port == "":
syslog.syslog("knockknock.PortOpener: Parent process is closed. Terminating.")
syslog.syslog("knocknock3.PortOpener: Parent process is closed. Terminating.")
os._exit(4)
description = 'INPUT -m limit --limit 1/minute --limit-burst 1 -m state --state NEW -p tcp -s ' + sourceIP + ' --dport ' + str(port) + ' -j ACCEPT'
@ -50,5 +50,5 @@ class PortOpener:
self.stream.write(str(port) + "\n")
self.stream.flush()
except:
syslog.syslog("knockknock: Error, PortOpener process has died. Terminating.")
syslog.syslog("knocknock3: Error, PortOpener process has died. Terminating.")
os._exit(4)

@ -40,16 +40,18 @@ def createDaemon():
try:
pid = os.fork()
except(OSError, e):
raise Exception("%s [%d]" % (e.strerror, e.errno))
except OSError:
tb = sys.exc_info()[2]
raise Exception("OSError").with_traceback(tb)
if (pid == 0): # The first child.
os.setsid()
try:
pid = os.fork() # Fork a second child.
except(OSError, e):
raise Exception("%s [%d]" % (e.strerror, e.errno))
except OSError:
tb = sys.exc_info()[2]
raise Exception("OSError").with_traceback(tb)
if (pid == 0): # The second child.
os.chdir(WORKDIR)

@ -1,8 +1,8 @@
#!/bin/sh
# This script provides the minimal firewall rules necessary to run
# knockknock. Essentially, no connections are allowed, unless they
# are authenticated with knockknock.
# knocknock. Essentially, no connections are allowed, unless they
# are authenticated with knocknock.
#
# Courtesy: Jake Appelbaum
@ -25,4 +25,4 @@ $IPTABLES -A REJECTLOG -p tcp -j REJECT --reject-with tcp-reset
$IPTABLES -A REJECTLOG -j REJECT
# Reject all other incoming traffic:
$IPTABLES -A INPUT -j REJECTLOG
$IPTABLES -A INPUT -j REJECTLOG

@ -2,28 +2,28 @@ import sys, os, shutil
from distutils.core import setup, Extension
if sys.argv[1] != "sdist":
shutil.copyfile("knockknock-daemon.py", "knockknock/knockknock-daemon")
shutil.copyfile("knockknock-genprofile.py", "knockknock/knockknock-genprofile")
shutil.copyfile("knockknock-proxy.py", "knockknock/knockknock-proxy")
shutil.copyfile("knockknock.py", "knockknock/knockknock")
shutil.copyfile("knocknock3-daemon.py", "knocknock3/knocknock3-daemon")
shutil.copyfile("knocknock3-genprofile.py", "knocknock3/knocknock3-genprofile")
shutil.copyfile("knocknock3-proxy.py", "knocknock3/knocknock3-proxy")
shutil.copyfile("knocknock3.py", "knocknock3/knocknock3")
setup (name = 'knockknock',
setup (name = 'knocknock3',
version = '0.8',
description = 'A cryptographic single-packet port-knocker.',
author = 'Moxie Marlinspike',
author_email = 'moxie@thoughtcrime.org',
url = 'http://www.thoughtcrime.org/software/knockknock/',
url = 'http://www.thoughtcrime.org/software/knocknock/',
license = 'GPL',
packages = ["knockknock", "knockknock.proxy"],
scripts = ['knockknock/knockknock-daemon',
'knockknock/knockknock-genprofile',
'knockknock/knockknock-proxy',
'knockknock/knockknock'],
data_files = [("", ["minimal-firewall.sh", "knockknock-daemon.py",
"knockknock-genprofile.py", "knockknock-proxy.py",
"knockknock.py"]),
('share/knockknock', ['README', 'INSTALL', 'COPYING']),
('/etc/knockknock.d/', ['config'])]
packages = ["knocknock3", "knocknock3.proxy"],
scripts = ['knocknock3/knocknock3-daemon',
'knocknock3/knocknock3-genprofile',
'knocknock3/knocknock3-proxy',
'knocknock3/knocknock3'],
data_files = [("", ["minimal-firewall.sh", "knocknock3-daemon.py",
"knocknock3-genprofile.py", "knocknock3-proxy.py",
"knocknock3.py"]),
('share/knocknock3', ['README', 'INSTALL', 'COPYING']),
('/etc/knocknock3.d/', ['config'])]
)
print("Cleaning up...")
@ -32,10 +32,10 @@ if os.path.exists("build/"):
shutil.rmtree("build/")
try:
os.remove("knockknock/knockknock-proxy")
os.remove("knockknock/knockknock-daemon")
os.remove("knockknock/knockknock-genprofile")
os.remove("knockknock/knockknock")
os.remove("knocknock3/knocknock3-proxy")
os.remove("knocknock3/knocknock3-daemon")
os.remove("knocknock3/knocknock3-genprofile")
os.remove("knocknock3/knocknock3")
except:
pass