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

Support for SNI and dynamic certificate #98

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
abca316
Support for SNI and dynamic certificate
Sep 14, 2018
03ed32d
De-couple SSL support from HTTPListener
htnhan Jan 18, 2019
ac6a865
ProxyListener to support SSL and handle SSL traffic
htnhan Jan 18, 2019
772902e
certutil should only run on windows
htnhan Jan 18, 2019
5ca752b
Fix issue: ssl_remote_sock is undefined on Non-SSL sockets
htnhan Mar 8, 2019
f49a91b
make_socket() now has a fallback in case SSLContext() fails
htnhan Mar 23, 2019
63c1c58
rename make_socket() to wrap_socket()
htnhan Mar 23, 2019
71da060
SSLWrapper now initialize everything in __init__()
htnhan Mar 23, 2019
fcf6b5e
Use proper logging levels
htnhan Mar 23, 2019
1987f43
Clean up logic
htnhan Mar 23, 2019
a9e6005
Fix: failed logic to check make sure both certfile and keyfile exist
htnhan Mar 23, 2019
ed762b4
Fix missing :
htnhan Mar 23, 2019
d648c8d
Fix: Invalid syntax -- random back ticks
htnhan Mar 23, 2019
b923868
Various renames
htnhan Mar 23, 2019
430c5be
We now use traceback.format_exc() output
htnhan Mar 23, 2019
19b027d
More cleanup regarding ssl_utils and __init__.py
htnhan Mar 23, 2019
f477c5d
Pass network mode config to the listners
htnhan Mar 27, 2019
51d5f32
Remove old code
htnhan Mar 27, 2019
88a4b7f
Various fixes to add a fallback when failing to generate a cert
htnhan Mar 27, 2019
45ccd7f
Merge branch 'master' into feature-sni-and-dynamic-cert
strictlymike Mar 29, 2019
b53c91e
Exceptions and logging
strictlymike Mar 29, 2019
01be068
Exceptions and logging
strictlymike Mar 29, 2019
472fe25
Fix: Handling case https://<ipaddress>
htnhan Mar 31, 2019
675a65d
SSLWrapper should only be initialized once per listener
htnhan Apr 3, 2019
4a13e66
Listeners now create the SSLWrapper once per startup
htnhan Apr 9, 2019
e2395b3
Use ignore_errors instead of catch all except
htnhan Apr 9, 2019
f34814f
New template for HTTPS tests
htnhan Apr 9, 2019
054389e
New test cases for HTTPS
htnhan Apr 9, 2019
52b5b9f
ProxyListener does not use UseSSL config keyword
htnhan Apr 25, 2019
81ef1df
Merge branch 'master' into feature-sni-and-dynamic-cert
tinajohnson Dec 11, 2023
22a6f6c
Update SNI branch to Python 3
tinajohnson Dec 15, 2023
c5327ef
Fix to avoid use of TLSv1 or TLSv1_1
tinajohnson Dec 15, 2023
5567d85
Documentation update and Python 3.12 related modifications
tinajohnson Dec 28, 2023
acb0d96
Fix exception error message syntax
tinajohnson Dec 28, 2023
65ab931
Revert filemd5 change in test.py
tinajohnson Dec 29, 2023
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
20 changes: 14 additions & 6 deletions fakenet/configs/default.ini
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ NetworkMode: Auto
# DebugLevel: specify fine-grained debug print flags to enable. Enabling all
# logging when verbose mode is selected results in overwhelming output, hence
# this setting. Valid values (comma-separated) are:
#
#
# GENPKT Generic packet information
# GENPKTV Packet analysis, displays IP, TCP, UDP fields, very wide output
# CB Diverter packet handler callback start/finish logging
Expand Down Expand Up @@ -88,7 +88,7 @@ FixDNS: Yes
# ephemeral change.
ModifyLocalDNS: Yes

# Enable 'StopDNSService' to stop Windows DNS client to see the actual
# Enable 'StopDNSService' to stop Windows DNS client to see the actual
# processes resolving domains. This is a no-op on Linux, until such time as DNS
# caching is observed to interfere with finding the pid associated with a DNS
# request.
Expand All @@ -99,16 +99,16 @@ StopDNSService: Yes
# 'DefaultUDPListener' will handle TCP and UDP traffic going to unspecified ports.
#
# NOTE: Setting default UDP listener will intercept all DNS traffic unless you
# enable a dedicated UDP port 53 DNS listener or add UDP port 53 to the
# enable a dedicated UDP port 53 DNS listener or add UDP port 53 to the
# 'BlackListPortsUDP' below so that system's default DNS server is used instead.

RedirectAllTraffic: Yes
DefaultTCPListener: ProxyTCPListener
DefaultUDPListener: ProxyUDPListener

# Specify TCP and UDP ports to ignore when diverting packets.
# Specify TCP and UDP ports to ignore when diverting packets.
# For example, you may want to avoid diverting UDP port 53 (DNS) traffic
# when trying to intercept a specific process while allowing the rest to
# when trying to intercept a specific process while allowing the rest to
# function normally
#
# NOTE: This setting is only honored when 'RedirectAllTraffic' is enabled.
Expand All @@ -131,7 +131,7 @@ BlackListPortsUDP: 67, 68, 137, 138, 443, 1900, 5355
# Listener Configuration
#
# Listener configuration consists of generic settings used by the diverter which
# are the same for all listeners and listener specific settings.
# are the same for all listeners and listener specific settings.
#
# NOTE: Listener section names will be used for logging.
#
Expand Down Expand Up @@ -199,6 +199,11 @@ BlackListPortsUDP: 67, 68, 137, 138, 443, 1900, 5355
# hostname string, !hostname to insert the actual hostname
# of the system, or !random to generate a random hostname
# between 1 and 15 characters (inclusive).
# * Static_CA - Set FakeNet to use user provided CA certificate to sign generated certificates.
# * CA_Cert - CA certificate in PEM format to be used when Static_CA config is set. Manually
# add this certificate to Windows trust store before executing FakeNet.
# * CA_Key - CA private key in PEM format to be used when Static_CA config is set.


[ProxyTCPListener]
Enabled: True
Expand All @@ -207,6 +212,9 @@ Listener: ProxyListener
Port: 38926
Listeners: HTTPListener, RawListener, FTPListener, DNSListener, POPListener, SMTPListener, TFTPListener, IRCListener
Hidden: False
Static_CA: No
CA_Cert: configs/fakenet_ca.crt
CA_Key: configs/fakenet_ca.key

[ProxyUDPListener]
Enabled: True
Expand Down
19 changes: 19 additions & 0 deletions fakenet/configs/fakenet_ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDHzCCAgegAwIBAgIUdwSkHdOM2mMDw094Kha+9Z9/w60wDQYJKoZIhvcNAQEL
BQAwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAMMB2Zha2VuZXQwHhcNMjMxMjE0MDAx
NDUxWhcNMjQwMTEzMDAxNDUxWjAfMQswCQYDVQQGEwJVUzEQMA4GA1UEAwwHZmFr
ZW5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7pGzS8bX8M3SSQ
mk79puvqGBHwWVpDK82T44N/8mXHJ1R/7jMDq2wpkSjliiAE0mxPpkzMbr9mkeP/
/31GKAszbJYnurrxxYbLyOdRst2VqoXkWTia61lrsRIGcjwzKe2zyMCcuiyRTLcP
BmYd/ie5AzyHxitlS49cub+QkIODUAKTiZT3mPu6Yw2XvYkg+up69NzC0a/XexUv
PvgbBizquKj/YzMSp5X7ieYGv0xHf8Dhf3mqh9oLk35X/qV3LqdnVPjweCR8X9ze
yhfBbDr1VoBnOe2Nb5hlU9MB//A0hgDYj5TrHa4JrbNkv3lYMd4uv/CBW6o18Ba+
/zjEvyECAwEAAaNTMFEwHQYDVR0OBBYEFD3wRGMPQdWtBCKRy5c9N5YWnki2MB8G
A1UdIwQYMBaAFD3wRGMPQdWtBCKRy5c9N5YWnki2MA8GA1UdEwEB/wQFMAMBAf8w
DQYJKoZIhvcNAQELBQADggEBAGT5rmafrlv8VIXAgc0iazNd7A6rT7xNLkuF2JGK
7NV3yvsWM6SA+DlG7y70om+eKjd+qxzinxnSt6uFJhcdCqot1LU1u3OZDifTTJmk
31yEYp/+A93qjwe1Ag2rsVcztRl88KtsKrKNohv24iiWfIVDnHo0joerXoaGQwo6
zXl4GVJBEEAhf2GQRgyXcoWkSrsq8UKtVV9dI5QgIS6vZ65oNQEeoAXH56ihFUBX
hS+4Ko2FfUtxbfbw7tpDaNtqhAzJ+LE4RoDUepyCDXPha0Wb4giGOd5EEubYrFKi
DOdAMiiQT1WLK3/UnMlCOV4lne+g9JwBCXL8C0F0W1fFZY8=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions fakenet/configs/fakenet_ca.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDO6Rs0vG1/DN0k
kJpO/abr6hgR8FlaQyvNk+ODf/JlxydUf+4zA6tsKZEo5YogBNJsT6ZMzG6/ZpHj
//99RigLM2yWJ7q68cWGy8jnUbLdlaqF5Fk4mutZa7ESBnI8Mynts8jAnLoskUy3
DwZmHf4nuQM8h8YrZUuPXLm/kJCDg1ACk4mU95j7umMNl72JIPrqevTcwtGv13sV
Lz74GwYs6rio/2MzEqeV+4nmBr9MR3/A4X95qofaC5N+V/6ldy6nZ1T48HgkfF/c
3soXwWw69VaAZzntjW+YZVPTAf/wNIYA2I+U6x2uCa2zZL95WDHeLr/wgVuqNfAW
vv84xL8hAgMBAAECggEAAyp6KDPcHCjH5XU4hXGPeGYvkhldQtxqsw2Rr7xpVWrl
dw1q8/dR2kVGVFSlBWe7tIPk0Ew8fD14+xtXG4xhmECAoElTHY+b7VgxkVJPem9h
RD4XOLsP4ba4rlNes+DiUCHKbyHTOox1RXytQZxNbgbVr7tOVNU1nf0rVmzt9Zbw
uPltpCcL+yvnaWmBUgdCLIhIT/HDrp4+uZP+zW7pVm/KMQL0I9OMnm6dCimP88pU
meepDRdxHkHVb347jx0+nWSH2V63wxH6WR8lAb4oAXeQXUgS8Q0lXh70EW/x0Ut3
neB/mfuaXLVrBcBTbhPTU7PKd/Sc+dkkqhEpNRR3dQKBgQDyLNPyWEJVXwQ6iOom
xxyqm61DZw8IpBYVmfYrOisTUWVC+oNlpsNPzWsgwmWzpcJ8s6ykupWFcWZeJv2h
XPlq+Ai6Ky0v+yESiUtNb+lKuXGvHqTpTxvPgL/20ZMfRIkWs9YBLA+aTh5RC8Vs
i12fRW9JTZTKgyf7PEkj+DjCCwKBgQDauOszqtFs6d36AMVJJ7OlmZnEWaELv9bW
ns7kdeBgr35gzGbDOkyQGBII5SCwpgWbXyxT39T9xuNoWCWXSZdHDco/UlAG47qI
Pq/KmtbrKxvg6yKsPIDV+cexuBrLIvzsaz8qPbfE/W7nxf+FtvDhvnGyqoiYd3DS
XSD5HcwLAwKBgQDdQpG+mF66qx4s8Myl80NAqQ1LSMyWg3xd7hXYdsPGWZaf9Eu6
wvstXSvkeVf8I5Um4+33bzWO/wWdPhh6pnyG++jVVv9pGBOmYOP48yd9iyLP8bqQ
IyPwmNxKgD3f0nlB0brTxVLYE0llmNCelFJMY18C5SvtPpl31COrBm2s8wKBgG8D
zN28pe+SBIkQOxKWhChZfiKbG5LLHFBy6rAq5GguqwaWuNH+lT3N+dlp8t22ZsIl
3Gn2AjWM7X/Yvbu8LnxyE2Vwcg4NKHBe4PsE/HEAwHW44zBoxTvWO/WIbJEOgTG+
faEDEnN57wDVDozf/gOWlj8JL6uzdCBSBJps9VPhAoGAWQUkdpxRxEARhL7wYR7g
EidDWKnULiULjlrP7VPMJ5hrZf5PmWyZLWW3SkEUhcf25CnJoUoq1OOB1GjL9lBL
0+tXalLnA/mRxO5ILzwJivHyJKnljuPKyXmpKt8H4KRUXV3Uk2may58Jwn8InuRE
aW956i0O1tgrDOj3tSAT8KI=
-----END PRIVATE KEY-----
2 changes: 1 addition & 1 deletion fakenet/fakenet.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def start(self):
self.logger.error("%s" % e)

else:

listener_config['networkmode'] = self.diverter_config['networkmode']
listener_provider_instance = listener_provider(
listener_config, listener_name, self.logging_level)

Expand Down
2 changes: 1 addition & 1 deletion fakenet/listeners/DNSListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class DNSListener(object):

def taste(self, data, dport):

confidence = 1 if dport is 53 else 0
confidence = 1 if dport == 53 else 0

try:
d = DNSRecord.parse(data)
Expand Down
37 changes: 22 additions & 15 deletions fakenet/listeners/HTTPListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import time

from .ssl_utils import SSLWrapper
from . import *

MIME_FILE_RESPONSE = {
Expand Down Expand Up @@ -137,6 +138,10 @@ def respond(self, req, meth, postdata=None):


class HTTPListener(object):
SSL_UTILS = os.path.join("listeners", "ssl_utils")
CA_CERT = os.path.join(SSL_UTILS, "server.pem")
CA_KEY = os.path.join(SSL_UTILS, "privkey.pem")
NOT_AFTER_DELTA_SECONDS = 300 * 24 * 60 * 60

def taste(self, data, dport):

Expand Down Expand Up @@ -168,11 +173,13 @@ def __init__(

self.logger = logging.getLogger(name)
self.logger.setLevel(logging_level)

self.config = config
self.name = name
self.local_ip = config.get('ipaddr')
self.server = None
self.port = self.config.get('port', 80)
self.sslwrapper = None

self.logger.debug('Initialized with config:')
for key, value in config.items():
Expand All @@ -185,29 +192,29 @@ def __init__(
self.logger.error('Could not locate webroot directory: %s', path)
sys.exit(1)


def start(self):
self.logger.debug('Starting...')
self.server = ThreadedHTTPServer((self.local_ip, int(self.config.get('port'))), ThreadedHTTPRequestHandler)

self.server = ThreadedHTTPServer((self.local_ip,
int(self.config.get('port'))), ThreadedHTTPRequestHandler)
self.server.logger = self.logger
self.server.config = self.config
self.server.webroot_path = self.webroot_path
self.server.extensions_map = self.extensions_map

if self.config.get('usessl') == 'Yes':
self.logger.debug('Using SSL socket.')

keyfile_path = 'listeners/ssl_utils/privkey.pem'
keyfile_path = ListenerBase.abs_config_path(keyfile_path)
if keyfile_path is None:
raise RuntimeError('Could not locate %s' % (keyfile_path))

certfile_path = 'listeners/ssl_utils/server.pem'
certfile_path = ListenerBase.abs_config_path(certfile_path)
if certfile_path is None:
raise RuntimeError('Could not locate %s' % (certfile_path))

self.server.socket = ssl.wrap_socket(self.server.socket, keyfile=keyfile_path, certfile=certfile_path, server_side=True, ciphers='RSA')
self.logger.debug("HTTP Listener starting with SSL")
config = {
'cert_dir': self.config.get('cert_dir', 'configs/temp_certs'),
'networkmode': self.config.get('networkmode', None),
'static_ca': self.config.get('static_ca', "No"),
'ca_cert': self.config.get('ca_cert'),
'ca_key': self.config.get('ca_key')
}
self.sslwrapper = SSLWrapper(config)
self.server.sslwrapper = self.sslwrapper
self.server.socket = self.server.sslwrapper.wrap_socket(
self.server.socket)

self.server.custom_responses = []
custom = self.config.get('custom')
Expand Down
49 changes: 19 additions & 30 deletions fakenet/listeners/ProxyListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
import logging
import ssl
from OpenSSL import SSL
from .ssl_utils import ssl_detector
from .ssl_utils import ssl_detector, SSLWrapper
from . import *
import os
import traceback

BUF_SZ = 1024

class ProxyListener(object):

class ProxyListener(object):

def __init__(
self,
Expand All @@ -42,6 +43,7 @@ def __init__(
self.logger.debug('Initialized with config:')
for key, value in config.items():
self.logger.debug(' %10s: %s', key, value)


def start(self):

Expand All @@ -50,10 +52,18 @@ def start(self):

if proto == 'TCP':

self.logger.debug('Starting TCP ...')

self.logger.debug('Starting TCP ...')
config = {
'cert_dir': self.config.get('cert_dir', 'configs/temp_certs'),
'networkmode': self.config.get('networkmode', None),
'static_ca': self.config.get('static_ca', False),
'ca_cert': self.config.get('ca_cert'),
'ca_key': self.config.get('ca_key')
}
self.sslwrapper = SSLWrapper(config)
self.server = ThreadedTCPServer((self.local_ip,
int(self.config.get('port'))), ThreadedTCPRequestHandler)
self.server.sslwrapper = self.sslwrapper

elif proto == 'UDP':

Expand Down Expand Up @@ -161,7 +171,6 @@ def get_top_listener(config, data, listeners, diverter, orig_src_ip,

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):


def handle(self):

remote_sock = self.request
Expand All @@ -171,22 +180,6 @@ def handle(self):
remote_q = queue.Queue()
data = None

ssl_remote_sock = None

keyfile_path = 'listeners/ssl_utils/privkey.pem'
keyfile_path = ListenerBase.abs_config_path(keyfile_path)
if keyfile_path is None:
self.logger.error('Could not locate %s', keyfile_path)
sys.exit(1)

certfile_path = 'listeners/ssl_utils/server.pem'
certfile_path = ListenerBase.abs_config_path(certfile_path)
if certfile_path is None:
self.logger.error('Could not locate %s', certfile_path)
sys.exit(1)

ssl_version = ssl.PROTOCOL_SSLv23

try:
data = remote_sock.recv(BUF_SZ, socket.MSG_PEEK)

Expand All @@ -200,17 +193,13 @@ def handle(self):
self.server.logger.warning('recv() error: %s' % e.message)

if data:

if ssl_detector.looks_like_ssl(data):
self.server.logger.debug('SSL detected')
ssl_remote_sock = ssl.wrap_socket(
remote_sock,
server_side=True,
do_handshake_on_connect=True,
certfile=certfile_path,
ssl_version=ssl_version,
keyfile=keyfile_path )
ssl_remote_sock = self.server.sslwrapper.wrap_socket(remote_sock)
data = ssl_remote_sock.recv(BUF_SZ)

else:
ssl_remote_sock = None


orig_src_ip = self.client_address[0]
orig_src_port = self.client_address[1]
Expand Down
Loading