├── .gitignore
├── README
├── README.md
├── app.py
├── gunicorn.conf.py
├── requirements.txt
├── settings.py
└── start.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 |
5 | # C extensions
6 | *.so
7 |
8 | # Distribution / packaging
9 | .Python
10 | env/
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | lib/
17 | lib64/
18 | parts/
19 | sdist/
20 | var/
21 | *.egg-info/
22 | .installed.cfg
23 | *.egg
24 |
25 | # PyInstaller
26 | # Usually these files are written by a python script from a template
27 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
28 | *.manifest
29 | *.spec
30 |
31 | # Installer logs
32 | pip-log.txt
33 | pip-delete-this-directory.txt
34 |
35 | # Unit test / coverage reports
36 | htmlcov/
37 | .tox/
38 | .coverage
39 | .cache
40 | nosetests.xml
41 | coverage.xml
42 |
43 | # Translations
44 | *.mo
45 | *.pot
46 |
47 | # Django stuff:
48 | *.log
49 |
50 | # Sphinx documentation
51 | docs/_build/
52 |
53 | # PyBuilder
54 | target/
55 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | DESCRIPTION
2 |
3 | testcookie-recaptcha-processor is a simple web server proxying recaptcha responses to Google.
4 | Server should be used with testcookie-nginx-module for setting cookies after solving recaptchas.
5 |
6 | NOTE
7 |
8 | This project is Proof-of-Contept for those people, who ask me to add "Captcha functionality" to testcookie-nginx-module.
9 | Check the "doc" directory for the list of things you can do yourself.
10 |
11 | INSTALLATION
12 |
13 | Grab and install libraries:
14 | *) pip install -r requirements.txt
15 |
16 | Build nginx with testcookie-nginx-module, use example configuration.
17 | Set REcaptcha public key in nginx config and REcaptcha private key in settings.py config.
18 | Run testcookie-recaptcha-processor, run nginx.
19 |
20 |
21 | EXAMPLE CONFIGURATION
22 |
23 | server {
24 | listen 80;
25 | server_name domain.com;
26 |
27 | testcookie off;
28 | testcookie_name BPC;
29 | testcookie_secret keepmescret;
30 | testcookie_session $remote_addr;
31 | testcookie_arg attempt;
32 | testcookie_max_attempts 3;
33 | testcookie_fallback /cookies.html?backurl=http://$host$request_uri;
34 | testcookie_get_only on;
35 | testcookie_redirect_via_refresh on;
36 | testcookie_refresh_template "
";
37 |
38 | location = /cookies.html {
39 | root /var/www/public_html;
40 | }
41 |
42 | location = /captcha {
43 | testcookie var;
44 | proxy_set_header Testcookie-Domain "domain.com";
45 | proxy_set_header Testcookie-Value $testcookie_set;
46 | proxy_set_header Testcookie-Nexturl $testcookie_nexturl;
47 | proxy_set_header Testcookie-Name "BPC";
48 | proxy_set_header X-Real-IP $remote_addr;
49 | proxy_pass http://127.0.0.1:10101/;
50 | }
51 |
52 | location / {
53 | testcookie on;
54 | proxy_set_header Host $host;
55 | proxy_set_header X-Real-IP $remote_addr;
56 | proxy_pass http://127.0.0.1:8080;
57 | }
58 | }
59 |
60 |
61 | SOURCES
62 |
63 | Available on github at kyprizel/testcookie-recaptcha-processor
64 | ().
65 |
66 | BUGS
67 |
68 | Feel free to report bugs and send patches to kyprizel@gmail.com
69 | or use github's issue tracker().
70 |
71 | COPYRIGHT & LICENSE
72 |
73 | Copyright (C) 2012 Eldar Zaitov (kyprizel@gmail.com).
74 |
75 | All rights reserved.
76 |
77 | This module is licenced under the terms of BSD license.
78 |
79 | Redistribution and use in source and binary forms, with or without
80 | modification, are permitted provided that the following conditions are
81 | met:
82 |
83 | * Redistributions of source code must retain the above copyright
84 | notice, this list of conditions and the following disclaimer.
85 |
86 | * Redistributions in binary form must reproduce the above copyright
87 | notice, this list of conditions and the following disclaimer in the
88 | documentation and/or other materials provided with the distribution.
89 |
90 | * Neither the name of the authors nor the names of its contributors
91 | may be used to endorse or promote products derived from this
92 | software without specific prior written permission.
93 |
94 | THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
95 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
96 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
97 | ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
98 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
99 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
100 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
101 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
102 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
103 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
104 | SUCH DAMAGE.
105 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Description
2 | ===========
3 |
4 | **testcookie-recaptcha-processor** is a simple web server proxying recaptcha responses to Google.
5 | Server should be used with [testcookie-nginx-module](http://github.com/kyprizel/testcookie-nginx-module) for setting cookies after solving recaptchas.
6 |
7 | Note
8 | ====
9 |
10 | This project is Proof-of-Contept for those people, who ask me to add "Captcha functionality" to testcookie-nginx-module.
11 |
12 | Installation
13 | ============
14 |
15 | Grab and install libraries:
16 | *) pip install -r requirements.txt
17 | *) start.sh
18 |
19 | Build nginx with testcookie-nginx-module, use example configuration.
20 | Run testcookie-recaptcha-processor, run nginx.
21 |
22 |
23 | Example configuration
24 | =====================
25 |
26 | server {
27 | listen 80;
28 | server_name domain.com;
29 |
30 | testcookie off;
31 | testcookie_name BPC;
32 | testcookie_secret keepmescret;
33 | testcookie_session $remote_addr;
34 | testcookie_arg attempt;
35 | testcookie_max_attempts 3;
36 | testcookie_fallback /cookies.html?backurl=http://$host$request_uri;
37 | testcookie_get_only on;
38 | testcookie_redirect_via_refresh on;
39 | testcookie_refresh_template "";
40 |
41 | location = /captcha {
42 | testcookie var;
43 | proxy_set_header Testcookie-Domain "domain.com";
44 | proxy_set_header Testcookie-Value $testcookie_set;
45 | proxy_set_header Testcookie-Nexturl $testcookie_nexturl;
46 | proxy_set_header Testcookie-Name "BPC";
47 | proxy_set_header X-Real-IP $remote_addr;
48 | proxy_pass http://127.0.0.1:10101/;
49 | }
50 |
51 | location / {
52 | testcookie on;
53 | proxy_set_header Host $host;
54 | proxy_set_header X-Real-IP $remote_addr;
55 | proxy_pass http://127.0.0.1:8080;
56 | }
57 |
58 | location = /cookies.html {
59 | root /var/www/public_html;
60 | }
61 |
62 | }
63 |
64 |
65 | Sources
66 | =======
67 |
68 | Available on github at [kyprizel/testcookie-recaptcha-processor]
69 | ().
70 |
71 | Bugs
72 | ====
73 |
74 | Feel free to report bugs and send patches to kyprizel@gmail.com
75 | or use github's issue tracker().
76 |
77 | Copyright & License
78 | ===================
79 |
80 | Copyright (C) 2012 Eldar Zaitov (kyprizel@gmail.com).
81 |
82 | All rights reserved.
83 |
84 | This module is licenced under the terms of BSD license.
85 |
86 | Redistribution and use in source and binary forms, with or without
87 | modification, are permitted provided that the following conditions are
88 | met:
89 |
90 | * Redistributions of source code must retain the above copyright
91 | notice, this list of conditions and the following disclaimer.
92 |
93 | * Redistributions in binary form must reproduce the above copyright
94 | notice, this list of conditions and the following disclaimer in the
95 | documentation and/or other materials provided with the distribution.
96 |
97 | * Neither the name of the authors nor the names of its contributors
98 | may be used to endorse or promote products derived from this
99 | software without specific prior written permission.
100 |
101 | THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
102 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
103 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
104 | ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
105 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
106 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
107 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
108 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
109 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
110 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
111 | SUCH DAMAGE.
112 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | import json
5 | from geventhttpclient import HTTPClient, URL
6 | from flask import Flask, request, redirect, abort
7 |
8 | import settings
9 |
10 | app = Flask(__name__)
11 |
12 | def get_client_addr():
13 | if not request.headers.getlist("X-Real-IP"):
14 | ip = request.remote_addr
15 | else:
16 | ip = request.headers.getlist("X-Real-IP")[0]
17 | return ip
18 |
19 | def check_recaptcha(secret, resp, ip):
20 | try:
21 | url = URL('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s&ip=%s' % (secret, resp, ip))
22 | http = HTTPClient.from_url(url)
23 | response = http.get(url.request_uri)
24 | if response.status_code == 200:
25 | raw_res = response.read()
26 | res = json.loads(raw_res)
27 | if res.get('success'):
28 | return True
29 | except:
30 | pass
31 | return False
32 |
33 | @app.route('/', methods=['POST'])
34 | def handler():
35 | domain = request.headers.get('Testcookie-Domain', '')
36 | nexturl = request.headers.get('Testcookie-Nexturl', '/')
37 | cookie_name = request.headers.get('Testcookie-Name')
38 | cookie_val = request.headers.get('Testcookie-Value')
39 | secret = settings.RE_SECRETS.get(domain)
40 | if not cookie_name or not cookie_val or not secret:
41 | abort(500)
42 | ip = get_client_addr()
43 | if check_recaptcha(secret, request.form['g-recaptcha-response'], ip):
44 | resp = redirect(nexturl)
45 | resp.set_cookie(cookie_name, cookie_val)
46 | return resp
47 | return redirect(nexturl)
48 |
49 | if __name__ == '__main__':
50 | import logging
51 |
52 | logging.basicConfig(level=logging.DEBUG)
53 |
54 | app.debug = True
55 |
56 | app.run('localhost', 10101)
57 |
--------------------------------------------------------------------------------
/gunicorn.conf.py:
--------------------------------------------------------------------------------
1 | bind = "127.0.0.1:10101"
2 | workers = 10
3 | backlog = 2048
4 | #pidfile = "/home/recaptcher/run/server.pid"
5 | preload_app = True
6 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | geventhttpclient
2 | gunicorn
3 | flask
4 |
--------------------------------------------------------------------------------
/settings.py:
--------------------------------------------------------------------------------
1 | DEBUG=False
2 | RE_SECRETS = { 'example-domain1.com': 'per_domain_recaptcha_secret_key1',
3 | 'example-domain2.com': 'per_domain_recaptcha_secret_key2' }
4 |
5 |
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | gunicorn -c gunicorn.conf.py app:app
4 |
--------------------------------------------------------------------------------