Skip to content

Instantly share code, notes, and snippets.

@kmonsoor
Created December 28, 2015 12:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kmonsoor/87e2dd9dc6b1d1033cdf to your computer and use it in GitHub Desktop.
Save kmonsoor/87e2dd9dc6b1d1033cdf to your computer and use it in GitHub Desktop.
to allow verified domain users the ability to add sites to a Squid Proxy whitelist via a secure web form
'''
SOURCE: http://pastebin.com/48G4MS8E
The code below was used to allow verified domain users the ability to add sites to a Squid Proxy whitelist via a secure web form.
It deals with Flask-Apache-SSL-LDAP-Email-Sockets-Logging and other topics
I make no claims as to it's suitability for other purposes.
I am not posting this for anyones approval nor is it here to be shot down.
This code is provided as-is simply to assist others in trying to setup a similar Python(Flask)->Apache->SSL deployment.
All code was run on Windows Server 2008 R2 (64bit) { don't judge me :) }
The following (Win 32 bit ONLY) software versions were used:
Python 2.7.10
Apache 2.4.17-win32-VC14 + SSL
mod_wsgi-4.4.21+ap24vc9-cp27-none-win32
pywin32-219.win32-py2.7
MS Visual C++ 2015 Redist x86
Squid 3.5.5
***************
** webapp.py ** This file goes in your Flask App 'root' folder
***************
'''
from flask import Flask, render_template, request
import ldap
import re
import os
import win32serviceutil
import socket
import time
import smtplib
from email.mime.text import MIMEText
app = Flask(__name__)
@app.route("/")
# display web page
def main():
return render_template('index.htm')
# Sends an email to {admin_email@address} to notify the change
def send_email_to_ME(domain,username,url):
try:
_from = '{server_email@address}'
_to = '{admin_email@address}'
_smtp_server = '{smtp server IP or URL}'
msg = MIMEText('%s\%s added the URL: %s to the {your server name} whitelist on %s\n\nActions:\n\tCheck and validate the URL.' %(domain,username,url,time.strftime("%Y-%m-%d %H:%M")))
msg['Subject'] = 'New Addition To Whitelist'
msg['From'] = _from
msg['To'] = _to
s = smtplib.SMTP(_smtp_server)
s.sendmail(_from, [_to], msg.as_string())
s.quit
return True
except Exception as e:
write_to_admin_log(e)
return False
# checks the hostname is valid
def is_valid_hostname(hostname):
try:
if socket.gethostbyname(hostname):
return True
else:
return False
except Exception as e:
write_to_admin_log(e)
return False
# scans to the end of the whitelist file then adds the new URL
def add_to_whitelist(url):
try:
with open("{full path to whitelist}", "r+") as fo:
for line in fo:
pass
with open("{full path to whitelist}", "a") as fo:
if line.endswith('\n'):
fo.write(".%s\n" % url)
else:
fo.write("\n.%s\n" % url)
return True
except Exception as e:
write_to_admin_log(e)
return False
# returns True if URL is NOT in the whitelist
def not_in_whitelist(url):
try:
test = True;
with open("{full path to whitelist}", "r+") as fo:
for line in fo:
if '.'+url == line.replace("\n", ""):
test = False
break
return test
except Exception as e:
write_to_admin_log(e)
return False
# Does an LDAP bind to verify the user credentials
def is_user_valid (username, password, domain=None):
Server = "ldap://"+domain+".your.domain.com"
DN = domain+"\\"+username
Base = "dc="+domain+",dc=your,dc=domain,dc=com"
Scope = ldap.SCOPE_SUBTREE
Filter = "(&(objectClass=user)(sAMAccountName="+username+"))"
try:
l = ldap.initialize(Server)
l.set_option(ldap.OPT_REFERRALS, 0)
l.protocol_version = 3
s = l.simple_bind_s(DN, password)
l.unbind()
if s:
return True
else:
return False
except Exception as e:
write_to_admin_log(e)
return False
# Restarts the required service by name
def restart_service(service):
try:
win32serviceutil.RestartService(service)
return True
except Exception as e:
write_to_admin_log(e)
return False
# Writes out to a log file recording the whitelist change
def write_to_whitelist_log(url,username):
try:
with open("{full path to whitelist log file}", "a+") as fo:
fo.write('%s added by %s on %s\n' %(url,username,time.strftime("%Y-%m-%d %H:%M")))
return True
except Exception as e:
write_to_admin_log(e)
return False
# Writes out (mostly errors) to an admin log file
def write_to_admin_log(log_msg):
try:
with open("{full path to admin log file}", "a+") as fo:
fo.write('%s - %s\n' %(time.strftime("%Y-%m-%d %H:%M"), log_msg))
return True
except Exception as e:
print e
return False
# Handles the form being submitted
@app.route('/addurl',methods=['POST'])
def addURL():
_url = str(request.form['url'])
_user = str(request.form['user'])
_pass = str(request.form['pass'])
_dom = str(request.form['domain'])
if _url and _user and _pass:
if is_user_valid(_user,_pass,_dom):
if is_valid_hostname(_url):
if not_in_whitelist(_url):
if add_to_whitelist(_url):
write_to_whitelist_log(_url,_user)
restart_service('squidsrv')
send_email_to_ME(_dom,_user,_url)
return "<font style='color:#00ff00;'>URL added to whitelist.</font>"
else:
write_to_admin_log('ERROR::Failed to add URL')
return "<font style='color:#ff0000;'>Failed to add URL</font>"
else:
return "<font style='color:#ff0000;'>URL already whitelisted</font>"
else:
write_to_admin_log('ERROR::Invalid Hostname! - %s' % _url)
return "<font style='color:#ff0000;'>Invalid Hostname!</font>"
else:
write_to_admin_log('ERROR::Invalid User Credentials! - user:%s pass:%s' %(_user, _pass))
return "<font style='color:#ff0000;'>Invalid User Credentials!</font>"
else:
return "<font style='color:#ff0000;'>Missing Information!</font>"
# starts the app locally (not used by Apache)
if __name__ == "__main__":
app.run(host="{your hostname}")
*****************
** webapp.wsgi ** Should reside in the same directory as webapp.py(above)
*****************
import sys
#Expand Python classes path with your app's path
sys.path.insert(0, "{full path to webapp.py directory}")
sys.path.append("{full path to squid whitelist directory}")
from webapp import app
#Initialize WSGI app object
application = app
*****************
** apache.conf **
*****************
*** Note: Below are listed the changes needed to a default apache.conf file
Listen 443
LoadModule socache_dbm_module modules/mod_socache_dbm.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule wsgi_module modules/mod_wsgi.so
#Include conf/extra/httpd-ssl.conf
WSGIRestrictStdout Off
ServerName {server hostname}
SSLSessionCache "dbm:c:/Apache24/logs/ssl_scache"
SSLSessionCacheTimeout 300
<VirtualHost *:443>
SSLEngine on
SSLProtocol all
SSLCipherSuite HIGH:MEDIUM
SSLCertificateFile "C:/apache24/SSL/certificate.cer"
SSLCertificateKeyFile "c:/apache24/SSL/certificate.key"
SSLCertificateChainFile "c:/apache24/ssl/intermediate.cer"
ServerName {server hostname}
WSGIScriptAlias / {full path to webapp.wsgi}
<Directory {full path to webapp.py directory}>
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
<Files *.wsgi>
MultiviewsMatch Any
SetHandler wsgi-script
Options ExecCGI
Order allow,deny
Allow from all
</Files>
</VirtualHost>
"""
***************
** index.htm **
***************
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Manage Whitelist</title>
<script src="../static/js/jquery.js"></script>
<link href="../static/main.css" rel="stylesheet">
<script>
EnableSubmit = function(val) {
var sbmt = document.getElementById("btnAddURL");
if (val.checked == true) {
sbmt.disabled = false;
} else {
sbmt.disabled = true;
}
}
</script>
</head>
<body>
<script>
$body = $("body");
$(document).on({
ajaxStart: function() {
$body.addClass("loading");
},
ajaxStop: function() {
$body.removeClass("loading");
}
});
$(function() {
$('#btnAddURL').click(function() {
$.ajax({
url: '/addurl',
data: $('form').serialize(),
type: 'POST',
success: function(response) {
document.getElementById('responseMsg').innerHTML = response;
},
error: function(response) {
document.getElementById('responseMsg').innerHTML = response;
}
});
});
});
</script>
<div id="titles">
<h2>Internet Gateway Whitelist Form</h2>
</div>
<hr>
<div id="content">
<p>You can add a domain to the Internet Gateway Whitelist using the form below.</p>
<strike>https://www.google.co.uk/intl/en/about/</strike>
<br/>
<strike>https://www.google.co.uk</strike>
<br/>
<br/>
<form class="form-whitelist" method="post">
<input type="text" name="url" id="url" class="form-control" placeholder="google.co.uk" required style="width: 485px;">
<p>Please enter your domain/user credentials:</p>
<select name="domain">
<option value="lima">LIma</option>
<option value="osca">OSca</option>
</select>\
<input type="text" name="user" id="user" class="form-control" placeholder="username" required style="width: 200px;">&nbsp;
<input type="password" name="pass" id="pass" class="form-control" placeholder="password" required style="width: 200px;">
<br/>
<br/>
<input type="checkbox" id="Accept" name="agree" value="agree" onClick="EnableSubmit(this)">I agree that the website I am adding is for buisness use ONLY and as such
<br/>does not contain any content that under UK Law would be considered illegal
<br/>or inappropriate.
<br/>
<br/>
<div>
<button id="btnAddURL" class="btn" type="button" disabled>Add URL</button>&nbsp;&nbsp;<span id="responseMsg"></span>
</div>
</form>
</div>
<hr>
<div id="footer">
<script type="text/javascript">
document.write('<p>Generated <span id="date-time">', new Date().toLocaleString(), '<\/span> by the SecureCloud+ Internet Gateway<\/p>')
</script>
</div>
</body>
</html>
<div class="modal"></div>
**************
** main.css **
**************
<!-- * {
font-family:verdana, sans-serif;
}
html body {
background:#efefef;
font-size:12px;
color:#1e1e1e;
overflow:hidden;
margin:0;
padding:0;
}
#titles {
margin-left:15px;
background:url('{path to your desired logo}') no-repeat left;
padding:10px 10px 10px 120px;
}
#content {
background:#fff;
padding:10px;
}
pre {
font-family:sans-serif;
}
hr {
margin:0;
}
#footer {
font-size:9px;
padding-left:10px;
}
body:lang(fa) {
direction:rtl;
font-size:100%;
font-family:Tahoma, Roya, sans-serif;
float:right;
}
:lang(he) {
direction:rtl;
}
.modal {
display:none;
position:fixed;
z-index:1000;
top:0;
left:0;
height:100%;
width:100%;
background:rgba(255,255,255,.8) url(loader.gif) 50% 50% no-repeat;
}
body.loading {
overflow:hidden;
}
body.loading .modal {
display:block;
}
#titles h1,#titles h2 {
color:#000;
}
#***********************
#** ERR_ACCESS_DENIED **
#***********************
#*** Note: This is the squid template file usually found at C:\Squid\usr\share\squid\errors\{your language}\
#*** Note: At some convenient point in the HTML code add the following line
#<p>Click <a href="https://{server hostname}" onclick="javascript:void window.open('https://iproxy1.scpgateway.uk','1449481426672','width=520,height=400,toolbar=0,menubar=0,location=0,status=0,scrollbars=0,resizable=0,left=0,top=0');return false;"> here </a>to allow browsing to this site.</p>
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment