Merge branch 'master' into onedrive
commit
62588e436f
|
@ -38,7 +38,6 @@ class BibrecPage (Page.Page):
|
|||
dc.load_from_database (os.id)
|
||||
if not dc.files:
|
||||
# NOTE: Error message
|
||||
cherrypy.tools.rate_limiter.e404 ()
|
||||
raise cherrypy.HTTPError (404, _('No ebook by that number.'))
|
||||
|
||||
# add these fields so we won't have to test for their existence later
|
||||
|
|
|
@ -44,18 +44,16 @@ from SearchPage import BookSearchPage, AuthorSearchPage, SubjectSearchPage, Book
|
|||
from BibrecPage import BibrecPage
|
||||
import CoverPages
|
||||
import QRCodePage
|
||||
import StatsPage
|
||||
import CaptchaPage
|
||||
import Sitemap
|
||||
import Formatters
|
||||
import RateLimiter
|
||||
|
||||
import Timer
|
||||
|
||||
plugins.Timer = Timer.TimerPlugin
|
||||
|
||||
if six.PY3:
|
||||
CHERRYPY_CONFIG = ('/etc/autocat3.conf', os.path.expanduser ('~/.autocat3'))
|
||||
CHERRYPY_CONFIG = (os.path.expanduser ('~/.autocat3'), '/etc/autocat3.conf')
|
||||
# CCHERRYPY_CONFIG = ('/etc/autocat3.conf')
|
||||
else:
|
||||
CHERRYPY_CONFIG = ('/etc/autocat.conf', os.path.expanduser ('~/.autocat'))
|
||||
|
@ -140,12 +138,6 @@ def main ():
|
|||
Formatters.init ()
|
||||
cherrypy.log ("Continuing App Init", context = 'ENGINE', severity = logging.INFO)
|
||||
|
||||
try:
|
||||
cherrypy.tools.rate_limiter = RateLimiter.RateLimiterTool ()
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc ()
|
||||
cherrypy.log (tb, context = 'ENGINE', severity = logging.ERROR)
|
||||
|
||||
cherrypy.log ("Continuing App Init", context = 'ENGINE', severity = logging.INFO)
|
||||
cherrypy.tools.I18nTool = i18n_tool.I18nTool ()
|
||||
|
||||
|
@ -169,8 +161,6 @@ def main ():
|
|||
cherrypy.engine, params = GutenbergDatabase.get_connection_params (cherrypy.config))
|
||||
cherrypy.engine.pool.subscribe ()
|
||||
|
||||
plugins.RateLimiterReset (cherrypy.engine).subscribe ()
|
||||
plugins.RateLimiterDatabase (cherrypy.engine).subscribe ()
|
||||
plugins.Timer (cherrypy.engine).subscribe ()
|
||||
|
||||
cherrypy.log ("Daemonizing", context = 'ENGINE', severity = logging.INFO)
|
||||
|
@ -263,16 +253,7 @@ def main ():
|
|||
controller = Page.NullPage ())
|
||||
|
||||
d.connect ('stats', r'/stats/',
|
||||
controller = StatsPage.StatsPage ())
|
||||
|
||||
d.connect ('block', r'/stats/block/',
|
||||
controller = RateLimiter.BlockPage ())
|
||||
|
||||
d.connect ('unblock', r'/stats/unblock/',
|
||||
controller = RateLimiter.UnblockPage ())
|
||||
|
||||
d.connect ('traceback', r'/stats/traceback/',
|
||||
controller = RateLimiter.TracebackPage ())
|
||||
controller = Page.NullPage (), _static = True)
|
||||
|
||||
d.connect ('honeypot_send', r'/ebooks/send/megaupload/{id:\d+}.{filetype}',
|
||||
controller = Page.NullPage (), _static = True)
|
||||
|
|
3
Pipfile
3
Pipfile
|
@ -21,7 +21,6 @@ netaddr = "*"
|
|||
oauth = "*"
|
||||
oauthlib = "*"
|
||||
Pillow = "*"
|
||||
psycopg2 = "*"
|
||||
#pycurl = "*"
|
||||
#PyGObject = "*"
|
||||
pyparsing = "*"
|
||||
|
@ -40,7 +39,7 @@ SQLAlchemy = "*"
|
|||
#ufw = "*"
|
||||
#unattended-upgrades = "*"
|
||||
urllib3 = "*"
|
||||
adns = "==1.4-py0"
|
||||
psycopg2 = "==2.7.7"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "ee8fb05228d77d9d0e14c78195d3ead551470bbfb9d44c0cbe88444aefe72370"
|
||||
"sha256": "faa368c84714ecc94bc3f9b3a0bb08d4d8075fe70ae633afb9909ad5ae4f0bd5"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -16,13 +16,6 @@
|
|||
]
|
||||
},
|
||||
"default": {
|
||||
"adns": {
|
||||
"hashes": [
|
||||
"sha256:1176e63b66db007e8798150a9a7cfcca5d8a810ae488905f8b2b6b07e678f2ef"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.4-py0"
|
||||
},
|
||||
"babel": {
|
||||
"hashes": [
|
||||
"sha256:6778d85147d5d85345c14a26aada5e478ab04e39b078b0745ee6870c2b5cf669",
|
||||
|
@ -62,11 +55,11 @@
|
|||
},
|
||||
"cherrypy": {
|
||||
"hashes": [
|
||||
"sha256:4dd2f59b5af93bd9ca85f1ed0bb8295cd0f5a8ee2b84d476374d4e070aa5c615",
|
||||
"sha256:626e305bca3c5d56a16e5f7d64bc8a4e25d26c41be1779f585fad2608edbc4c8"
|
||||
"sha256:3c7b27fd1af4964434d821cd139b8d05c8f7fe4f37ae146fddb3f861d80a1da7",
|
||||
"sha256:6585c19b5e4faffa3613b5bf02c6a27dcc4c69a30d302aba819639a2af6fa48b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==18.1.0"
|
||||
"version": "==18.1.1"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
|
@ -123,41 +116,41 @@
|
|||
},
|
||||
"lxml": {
|
||||
"hashes": [
|
||||
"sha256:0358b9e9642bc7d39aac5cffe9884a99a5ca68e5e2c1b89e570ed60da9139908",
|
||||
"sha256:091a359c4dafebbecd3959d9013f1b896b5371859165e4e50b01607a98d9e3e2",
|
||||
"sha256:1998e4e60603c64bcc35af61b4331ab3af087457900d3980e18d190e17c3a697",
|
||||
"sha256:2000b4088dee9a41f459fddaf6609bba48a435ce6374bb254c5ccdaa8928c5ba",
|
||||
"sha256:2afb0064780d8aaf165875be5898c1866766e56175714fa5f9d055433e92d41d",
|
||||
"sha256:2d8f1d9334a4e3ff176d096c14ded3100547d73440683567d85b8842a53180bb",
|
||||
"sha256:2e38db22f6a3199fd63675e1b4bd795d676d906869047398f29f38ca55cb453a",
|
||||
"sha256:3181f84649c1a1ca62b19ddf28436b1b2cb05ae6c7d2628f33872e713994c364",
|
||||
"sha256:37462170dfd88af8431d04de6b236e6e9c06cda71e2ca26d88ef2332fd2a5237",
|
||||
"sha256:3a9d8521c89bf6f2a929c3d12ad3ad7392c774c327ea809fd08a13be6b3bc05f",
|
||||
"sha256:3d0bbd2e1a28b4429f24fd63a122a450ce9edb7a8063d070790092d7343a1aa4",
|
||||
"sha256:483d60585ce3ee71929cea70949059f83850fa5e12deb9c094ed1c8c2ec73cbd",
|
||||
"sha256:4888be27d5cba55ce94209baef5bcd7bbd7314a3d17021a5fc10000b3a5f737d",
|
||||
"sha256:64b0d62e4209170a2a0c404c446ab83b941a0003e96604d2e4f4cb735f8a2254",
|
||||
"sha256:68010900898fdf139ac08549c4dba8206c584070a960ffc530aebf0c6f2794ef",
|
||||
"sha256:872ecb066de602a0099db98bd9e57f4cfc1d62f6093d94460c787737aa08f39e",
|
||||
"sha256:88a32b03f2e4cd0e63f154cac76724709f40b3fc2f30139eb5d6f900521b44ed",
|
||||
"sha256:b1dc7683da4e67ab2bebf266afa68098d681ae02ce570f0d1117312273d2b2ac",
|
||||
"sha256:b29e27ce9371810250cb1528a771d047a9c7b0f79630dc7dc5815ff828f4273b",
|
||||
"sha256:ce197559596370d985f1ce6b7051b52126849d8159040293bf8b98cb2b3e1f78",
|
||||
"sha256:d45cf6daaf22584eff2175f48f82c4aa24d8e72a44913c5aff801819bb73d11f",
|
||||
"sha256:e2ff9496322b2ce947ba4a7a5eb048158de9d6f3fe9efce29f1e8dd6878561e6",
|
||||
"sha256:f7b979518ec1f294a41a707c007d54d0f3b3e1fd15d5b26b7e99b62b10d9a72e",
|
||||
"sha256:f9c7268e9d16e34e50f8246c4f24cf7353764affd2bc971f0379514c246e3f6b",
|
||||
"sha256:f9c839806089d79de588ee1dde2dae05dc1156d3355dfeb2b51fde84d9c960ad",
|
||||
"sha256:ff962953e2389226adc4d355e34a98b0b800984399153c6678f2367b11b4d4b8"
|
||||
"sha256:03984196d00670b2ab14ae0ea83d5cc0cfa4f5a42558afa9ab5fa745995328f5",
|
||||
"sha256:0815b0c9f897468de6a386dc15917a0becf48cc92425613aa8bbfc7f0f82951f",
|
||||
"sha256:175f3825f075cf02d15099eb52658457cf0ff103dcf11512b5d2583e1d40f58b",
|
||||
"sha256:30e14c62d88d1e01a26936ecd1c6e784d4afc9aa002bba4321c5897937112616",
|
||||
"sha256:3210da6f36cf4b835ff1be853962b22cc354d506f493b67a4303c88bbb40d57b",
|
||||
"sha256:40f60819fbd5bad6e191ba1329bfafa09ab7f3f174b3d034d413ef5266963294",
|
||||
"sha256:43b26a865a61549919f8a42e094dfdb62847113cf776d84bd6b60e4e3fc20ea3",
|
||||
"sha256:4a03dd682f8e35a10234904e0b9508d705ff98cf962c5851ed052e9340df3d90",
|
||||
"sha256:62f382cddf3d2e52cf266e161aa522d54fd624b8cc567bc18f573d9d50d40e8e",
|
||||
"sha256:7b98f0325be8450da70aa4a796c4f06852949fe031878b4aa1d6c417a412f314",
|
||||
"sha256:846a0739e595871041385d86d12af4b6999f921359b38affb99cdd6b54219a8f",
|
||||
"sha256:a3080470559938a09a5d0ec558c005282e99ac77bf8211fb7b9a5c66390acd8d",
|
||||
"sha256:ad841b78a476623955da270ab8d207c3c694aa5eba71f4792f65926dc46c6ee8",
|
||||
"sha256:afdd75d9735e44c639ffd6258ce04a2de3b208f148072c02478162d0944d9da3",
|
||||
"sha256:b4fbf9b552faff54742bcd0791ab1da5863363fb19047e68f6592be1ac2dab33",
|
||||
"sha256:b90c4e32d6ec089d3fa3518436bdf5ce4d902a0787dbd9bb09f37afe8b994317",
|
||||
"sha256:b91cfe4438c741aeff662d413fd2808ac901cc6229c838236840d11de4586d63",
|
||||
"sha256:bdb0593a42070b0a5f138b79b872289ee73c8e25b3f0bea6564e795b55b6bcdd",
|
||||
"sha256:c4e4bca2bb68ce22320297dfa1a7bf070a5b20bcbaec4ee023f83d2f6e76496f",
|
||||
"sha256:cec4ab14af9eae8501be3266ff50c3c2aecc017ba1e86c160209bb4f0423df6a",
|
||||
"sha256:e83b4b2bf029f5104bc1227dbb7bf5ace6fd8fabaebffcd4f8106fafc69fc45f",
|
||||
"sha256:e995b3734a46d41ae60b6097f7c51ba9958648c6d1e0935b7e0ee446ee4abe22",
|
||||
"sha256:f679d93dec7f7210575c85379a31322df4c46496f184ef650d3aba1484b38a2d",
|
||||
"sha256:fd213bb5166e46974f113c8228daaef1732abc47cb561ce9c4c8eaed4bd3b09b",
|
||||
"sha256:fdcb57b906dbc1f80666e6290e794ab8fb959a2e17aa5aee1758a85d1da4533f",
|
||||
"sha256:ff424b01d090ffe1947ec7432b07f536912e0300458f9a7f48ea217dd8362b86"
|
||||
],
|
||||
"version": "==4.3.2"
|
||||
"version": "==4.3.3"
|
||||
},
|
||||
"more-itertools": {
|
||||
"hashes": [
|
||||
"sha256:0125e8f60e9e031347105eb1682cef932f5e97d7b9a1a28d9bf00c22a5daef40",
|
||||
"sha256:590044e3942351a1bdb1de960b739ff4ce277960f2425ad4509446dbace8d9d1"
|
||||
"sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7",
|
||||
"sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"
|
||||
],
|
||||
"version": "==6.0.0"
|
||||
"version": "==7.0.0"
|
||||
},
|
||||
"netaddr": {
|
||||
"hashes": [
|
||||
|
@ -184,46 +177,42 @@
|
|||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e",
|
||||
"sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7",
|
||||
"sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a",
|
||||
"sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3",
|
||||
"sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1",
|
||||
"sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1",
|
||||
"sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7",
|
||||
"sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1",
|
||||
"sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3",
|
||||
"sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055",
|
||||
"sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf",
|
||||
"sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f",
|
||||
"sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f",
|
||||
"sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239",
|
||||
"sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe",
|
||||
"sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c",
|
||||
"sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697",
|
||||
"sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494",
|
||||
"sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356",
|
||||
"sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6",
|
||||
"sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000",
|
||||
"sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f",
|
||||
"sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c",
|
||||
"sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca",
|
||||
"sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8",
|
||||
"sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3",
|
||||
"sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad",
|
||||
"sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9",
|
||||
"sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc",
|
||||
"sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e"
|
||||
"sha256:15c056bfa284c30a7f265a41ac4cbbc93bdbfc0dfe0613b9cb8a8581b51a9e55",
|
||||
"sha256:1a4e06ba4f74494ea0c58c24de2bb752818e9d504474ec95b0aa94f6b0a7e479",
|
||||
"sha256:1c3c707c76be43c9e99cb7e3d5f1bee1c8e5be8b8a2a5eeee665efbf8ddde91a",
|
||||
"sha256:1fd0b290203e3b0882d9605d807b03c0f47e3440f97824586c173eca0aadd99d",
|
||||
"sha256:24114e4a6e1870c5a24b1da8f60d0ba77a0b4027907860188ea82bd3508c80eb",
|
||||
"sha256:258d886a49b6b058cd7abb0ab4b2b85ce78669a857398e83e8b8e28b317b5abb",
|
||||
"sha256:33c79b6dd6bc7f65079ab9ca5bebffb5f5d1141c689c9c6a7855776d1b09b7e8",
|
||||
"sha256:367385fc797b2c31564c427430c7a8630db1a00bd040555dfc1d5c52e39fcd72",
|
||||
"sha256:3c1884ff078fb8bf5f63d7d86921838b82ed4a7d0c027add773c2f38b3168754",
|
||||
"sha256:44e5240e8f4f8861d748f2a58b3f04daadab5e22bfec896bf5434745f788f33f",
|
||||
"sha256:46aa988e15f3ea72dddd81afe3839437b755fffddb5e173886f11460be909dce",
|
||||
"sha256:74d90d499c9c736d52dd6d9b7221af5665b9c04f1767e35f5dd8694324bd4601",
|
||||
"sha256:809c0a2ce9032cbcd7b5313f71af4bdc5c8c771cb86eb7559afd954cab82ebb5",
|
||||
"sha256:85d1ef2cdafd5507c4221d201aaf62fc9276f8b0f71bd3933363e62a33abc734",
|
||||
"sha256:8c3889c7681af77ecfa4431cd42a2885d093ecb811e81fbe5e203abc07e0995b",
|
||||
"sha256:9218d81b9fca98d2c47d35d688a0cea0c42fd473159dfd5612dcb0483c63e40b",
|
||||
"sha256:9aa4f3827992288edd37c9df345783a69ef58bd20cc02e64b36e44bcd157bbf1",
|
||||
"sha256:9d80f44137a70b6f84c750d11019a3419f409c944526a95219bea0ac31f4dd91",
|
||||
"sha256:b7ebd36128a2fe93991293f997e44be9286503c7530ace6a55b938b20be288d8",
|
||||
"sha256:c4c78e2c71c257c136cdd43869fd3d5e34fc2162dc22e4a5406b0ebe86958239",
|
||||
"sha256:c6a842537f887be1fe115d8abb5daa9bc8cc124e455ff995830cc785624a97af",
|
||||
"sha256:cf0a2e040fdf5a6d95f4c286c6ef1df6b36c218b528c8a9158ec2452a804b9b8",
|
||||
"sha256:cfd28aad6fc61f7a5d4ee556a997dc6e5555d9381d1390c00ecaf984d57e4232",
|
||||
"sha256:dca5660e25932771460d4688ccbb515677caaf8595f3f3240ec16c117deff89a",
|
||||
"sha256:de7aedc85918c2f887886442e50f52c1b93545606317956d65f342bd81cb4fc3",
|
||||
"sha256:e6c0bbf8e277b74196e3140c35f9a1ae3eafd818f7f2d3a15819c49135d6c062"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.4.1"
|
||||
"version": "==6.0.0"
|
||||
},
|
||||
"portend": {
|
||||
"hashes": [
|
||||
"sha256:b7ce7d35ea262415297cbfea86226513e77b9ee5f631d3baa11992d663963719",
|
||||
"sha256:f5c99a1aa1655733736bb0283fee6a1e115e18db500332bec8e24c43f320d8e8"
|
||||
"sha256:507e1f76eb6deec0cc15045d1140a07874f44d02eec021e8fd383557d99fe93d",
|
||||
"sha256:853d69e61d86aa1bc7a4976cb2f67efe1c92d3b41c47a5e6b8771d3c51b5bfd3"
|
||||
],
|
||||
"version": "==2.3"
|
||||
"version": "==2.4"
|
||||
},
|
||||
"psycopg2": {
|
||||
"hashes": [
|
||||
|
@ -263,19 +252,19 @@
|
|||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a",
|
||||
"sha256:f6c5ef0d7480ad048c054c37632c67fca55299990fff127850181659eea33fc3"
|
||||
"sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
|
||||
"sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.3.1"
|
||||
"version": "==2.4.0"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
|
||||
"sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c"
|
||||
"sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
|
||||
"sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2018.9"
|
||||
"version": "==2019.1"
|
||||
},
|
||||
"qrcode": {
|
||||
"hashes": [
|
||||
|
@ -302,18 +291,18 @@
|
|||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:0306149889c1a1bec362511f737bc446245ddfcdbe4b556abdfc506ed46dfa47",
|
||||
"sha256:4b08704a5939c698d2d5950b5dc950597613216cc8c01048efc0da860a0c3db9",
|
||||
"sha256:6ba0eb777ada6887062c2620e6d644b011078d5d3dc09119ae7107285f6f95e9",
|
||||
"sha256:7789cc323948792c4c62b269a56f2f2f9bc77d44e54fd81e01b12a967dd7244c",
|
||||
"sha256:825143aadca0da7d26eeaf2ab0f8bc33921a5642e570ded92dde08c5aaebc65f",
|
||||
"sha256:8fbd057faab28ce552d89c46f7a968e950f07e80752dfb93891dd11c6b0ee3b4",
|
||||
"sha256:a41aabb0b9072a14f1e2e554f959ed6439b83610ed656edace9096a0b27e378e",
|
||||
"sha256:d8807231aed332a1d0456d2088967b87e8c664222bed8e566384ca0ec0b43bfd",
|
||||
"sha256:dfd89b642fe71f4e8a9906455d4147d453061377b650e6233ddd9ea822971360"
|
||||
"sha256:020429dcf9b76cc7648a99c81b3a70154e45afebc81e0b85364457fe83b525e4",
|
||||
"sha256:0552802b1c3f3c7e4fee8c85e904a13c48226020aa1a0593246888a1ac55aaaf",
|
||||
"sha256:308965a80b92e1fec263ac1e4f1094317809a72bc4d26be2ec8a5fd026301175",
|
||||
"sha256:4d627feef04eb626397aa7bdec772774f53d63a1dc7cc5ee4d1bd2786a769d19",
|
||||
"sha256:93d1f9fcb1d25e0b4bd622eeba95b080262e7f8f55e5b43c76b8a5677e67334c",
|
||||
"sha256:c3859bbf29b1345d694f069ddfe53d6907b0393fda5e3794c800ad02902d78e9",
|
||||
"sha256:d56ce4c7b1a189094b9bee3b81c4aeb3f1ba3e375e91627ec8561b6ab483d0a8",
|
||||
"sha256:ebc5ef4e10fa3312fa1967dc0a894e6bd985a046768171f042ac3974fadc9680",
|
||||
"sha256:f9cd39066048066a4abe4c18fb213bc541339728005e72263f023742fb912585"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2019.3.12"
|
||||
"version": "==2019.4.14"
|
||||
},
|
||||
"repoze.lru": {
|
||||
"hashes": [
|
||||
|
@ -375,17 +364,17 @@
|
|||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:781fb7b9d194ed3fc596b8f0dd4623ff160e3e825dd8c15472376a438c19598b"
|
||||
"sha256:91c54ca8345008fceaec987e10924bf07dcab36c442925357e5a467b36a38319"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.1"
|
||||
"version": "==1.3.3"
|
||||
},
|
||||
"tempora": {
|
||||
"hashes": [
|
||||
"sha256:4951da790bd369f718dbe2287adbdc289dc2575a09278e77fad6131bcfe93097",
|
||||
"sha256:f8abbbd486eca3340bd3d242417b203c861d4e113ef778cd5fb9535b2b32ae54"
|
||||
"sha256:cb60b1d2b1664104e307f8e5269d7f4acdb077c82e35cd57246ae14a3427d2d6",
|
||||
"sha256:d28a03d2f64ee81aec6e6bff374127ef306fe00c1b7e27c7ff1618344221a699"
|
||||
],
|
||||
"version": "==1.14"
|
||||
"version": "==1.14.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
|
|
1124
RateLimiter-new.py
1124
RateLimiter-new.py
File diff suppressed because it is too large
Load Diff
1131
RateLimiter.py
1131
RateLimiter.py
File diff suppressed because it is too large
Load Diff
82
StatsPage.py
82
StatsPage.py
|
@ -1,82 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
StatsPage.py
|
||||
|
||||
Copyright 2009-2014 by Marcello Perathoner
|
||||
|
||||
Distributable under the GNU General Public License Version 3 or newer.
|
||||
|
||||
The appserver stats page.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import cherrypy
|
||||
|
||||
import BaseSearcher
|
||||
import TemplatedPage
|
||||
import asyncdns
|
||||
import ipinfo
|
||||
|
||||
|
||||
class StatsPage (TemplatedPage.TemplatedPage):
|
||||
""" Output some statistics. """
|
||||
|
||||
CONTENT_TYPE = 'application/xhtml+xml; charset=UTF-8'
|
||||
FORMATTER = 'html'
|
||||
|
||||
def index (self, **kwargs):
|
||||
""" Output stats. """
|
||||
|
||||
backends = int (BaseSearcher.sql_get ("SELECT count (*) from pg_stat_activity"))
|
||||
active_backends = int (BaseSearcher.sql_get (
|
||||
"SELECT count (*) - 1 from pg_stat_activity where current_query !~ '^<IDLE>'"))
|
||||
|
||||
ipsessions = list (cherrypy.tools.rate_limiter.cache.values ()) # pylint: disable=E1101
|
||||
|
||||
adns = asyncdns.AsyncDNS ()
|
||||
|
||||
# blocked IPs
|
||||
blocked = sorted ([s for s in ipsessions if s.get ('blocked', 0) >= 2],
|
||||
key = lambda s: s.ips.sort_key ())
|
||||
if 'resolve' in kwargs:
|
||||
for d in blocked:
|
||||
if d.ips.ipinfo is None:
|
||||
d.ips.ipinfo = ipinfo.IPInfo (adns, d.ips.get_ip_to_block ())
|
||||
|
||||
# active IPs
|
||||
active = sorted ([s for s in ipsessions if s.get ('active', False)],
|
||||
key = lambda s: s.ips.sort_key ())
|
||||
|
||||
# busiest IPs
|
||||
busiest = sorted ([s for s in active if s.get ('blocked', 0) < 2],
|
||||
key = lambda x: -x.get ('rhits'))[:10]
|
||||
if 'resolve' in kwargs:
|
||||
for d in busiest:
|
||||
if d.ips.ipinfo is None:
|
||||
d.ips.ipinfo = ipinfo.IPInfo (adns, d.ips.get_ip_to_block ())
|
||||
|
||||
# IPs with most sessions
|
||||
most_sessions = sorted ([s for s in active
|
||||
if not s.ips.whitelisted and len (s.sessions) > 1],
|
||||
key = lambda s: -len (s.sessions))[:10]
|
||||
if 'resolve' in kwargs:
|
||||
for d in most_sessions:
|
||||
if d.ips.ipinfo is None:
|
||||
d.ips.ipinfo = ipinfo.IPInfo (adns, d.ips.get_ip_to_block ())
|
||||
|
||||
adns.wait ()
|
||||
adns.cancel ()
|
||||
|
||||
return self.output ('stats',
|
||||
active = active,
|
||||
blocked = blocked,
|
||||
busiest = busiest,
|
||||
most_sessions = most_sessions,
|
||||
resolve = 'resolve' in kwargs,
|
||||
rl = cherrypy.tools.rate_limiter, # pylint: disable=E1101
|
||||
backends = backends,
|
||||
active_backends = active_backends)
|
200
asyncdns.py
200
asyncdns.py
|
@ -1,200 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
asyncdns.py
|
||||
|
||||
Copyright 2013-14 by Marcello Perathoner
|
||||
|
||||
Distributable under the GNU General Public License Version 3 or newer.
|
||||
|
||||
Higher level interface to the GNU asynchronous DNS library.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
import adns
|
||||
|
||||
# pass this to __init__ to use Google Public DNS
|
||||
RESOLV_CONF = 'nameserver 8.8.8.8'
|
||||
|
||||
# http://www.ietf.org/rfc/rfc1035.txt Domain Names
|
||||
# http://www.ietf.org/rfc/rfc3490.txt IDNA
|
||||
# http://www.ietf.org/rfc/rfc3492.txt Punycode
|
||||
|
||||
class AsyncDNS (object):
|
||||
""" An asynchronous DNS resolver. """
|
||||
|
||||
def __init__ (self, resolv_conf = None):
|
||||
if resolv_conf:
|
||||
self.resolver = adns.init (
|
||||
adns.iflags.noautosys + adns.iflags.noerrprint,
|
||||
sys.stderr, # FIXME: adns version 1.2.2 will allow keyword params
|
||||
resolv_conf)
|
||||
else:
|
||||
self.resolver = adns.init (
|
||||
adns.iflags.noautosys + adns.iflags.noerrprint)
|
||||
|
||||
self._queries = {} # keeps query objects alive
|
||||
|
||||
def query (self, query, callback, rr = adns.rr.A):
|
||||
""" Queue a query.
|
||||
|
||||
:param query: the query string (may contain unicode characters)
|
||||
:param callback: function taking a tuple of answers
|
||||
:param rr: the query rr type code
|
||||
|
||||
"""
|
||||
|
||||
if rr not in (adns.rr.PTR, adns.rr.PTRraw):
|
||||
query = self.encode (query)
|
||||
if rr in (adns.rr.PTR, adns.rr.PTRraw):
|
||||
self._queries [self.resolver.submit_reverse (query, rr)] = callback, rr
|
||||
else:
|
||||
self._queries [self.resolver.submit (query, rr)] = callback, rr
|
||||
|
||||
def query_dnsbl (self, query, zone, callback, rr = adns.rr.A):
|
||||
""" Queue a reverse dnsbl-type query. """
|
||||
self._queries [self.resolver.submit_reverse_any (query, zone, rr)] = callback, rr
|
||||
|
||||
def done (self):
|
||||
""" Are all queued queries answered? """
|
||||
return not self._queries
|
||||
|
||||
def wait (self, timeout = 10):
|
||||
""" Wait for the queries to complete. """
|
||||
|
||||
timeout += time.time ()
|
||||
while self._queries and time.time () < timeout:
|
||||
for q in self.resolver.completed (1):
|
||||
answer = q.check ()
|
||||
callback, rr = self._queries[q]
|
||||
del self._queries[q]
|
||||
|
||||
# print (answer)
|
||||
|
||||
a0 = answer[0]
|
||||
if a0 == 0:
|
||||
callback (self.decode_answer (rr, answer[3]))
|
||||
elif a0 == 101 and rr == adns.rr.A:
|
||||
# got CNAME, wanted A: resubmit
|
||||
self.query (answer[1], callback, rr)
|
||||
# else
|
||||
# pass
|
||||
|
||||
|
||||
def decode_answer (self, rr, answers):
|
||||
""" Decode the answer to unicode.
|
||||
|
||||
Supports only some rr types. You may override this to support
|
||||
some more.
|
||||
|
||||
"""
|
||||
|
||||
if rr in (adns.rr.A, adns.rr.TXT):
|
||||
# A records are ip addresses that need no decoding.
|
||||
# TXT records may be anything, even binary data,
|
||||
# so leave decoding to the caller.
|
||||
return answers
|
||||
|
||||
if rr in (adns.rr.PTR, adns.rr.PTRraw, adns.rr.CNAME, adns.rr.NSraw):
|
||||
return [ self.decode (host) for host in answers ]
|
||||
|
||||
if rr == adns.rr.MXraw:
|
||||
return [ (prio, self.decode (host)) for (prio, host) in answers ]
|
||||
|
||||
if rr == adns.rr.SRVraw:
|
||||
return [ (prio, weight, port, self.decode (host))
|
||||
for (prio, weight, port, host) in answers ]
|
||||
|
||||
if rr in (adns.rr.SOA, adns.rr.SOAraw):
|
||||
return [ (self.decode (mname), self.decode (rname),
|
||||
serial, refresh, retry, expire, minimum)
|
||||
for (mname, rname, serial, refresh,
|
||||
retry, expire, minimum) in answers ]
|
||||
|
||||
# unsupported HINFO, RP, RPraw, NS, SRV, MX
|
||||
|
||||
return answers
|
||||
|
||||
|
||||
@staticmethod
|
||||
def encode (query):
|
||||
""" Encode a unicode query to idna.
|
||||
|
||||
Result will still be of type unicode/str.
|
||||
"""
|
||||
return query.encode ('idna').decode ('ascii')
|
||||
|
||||
|
||||
@staticmethod
|
||||
def decode (answer):
|
||||
""" Decode an answer to unicode. """
|
||||
try:
|
||||
return answer.decode ('idna')
|
||||
except ValueError:
|
||||
return answer.decode ('ascii', 'replace')
|
||||
|
||||
|
||||
def cancel (self):
|
||||
""" Cancel all pending queries. """
|
||||
|
||||
for q in self._queries.keys ():
|
||||
q.cancel ()
|
||||
self._queries.clear ()
|
||||
|
||||
|
||||
def bulk_query (self, query_dict, rr):
|
||||
""" Bulk lookup.
|
||||
|
||||
:param dict: on entry { query1: None, query2: None }
|
||||
on exit { query1: (answer1, ), query2: (answer2a, answer2b) }
|
||||
|
||||
Note: you must call wait () after bulk_query () for the answers to appear
|
||||
|
||||
"""
|
||||
|
||||
def itemsetter (query):
|
||||
""" Return a callable object that puts the answer into
|
||||
the dictionary under the right key. """
|
||||
def g (answer):
|
||||
""" Put the answer into the dictionary. """
|
||||
query_dict[query] = answer
|
||||
# print "put: " + answer
|
||||
return g
|
||||
|
||||
for query in query_dict.keys ():
|
||||
if query:
|
||||
self.query (query, itemsetter (query), rr)
|
||||
|
||||
|
||||
def bulk_query (dict_, rr = adns.rr.A, timeout = 10):
|
||||
""" Perform bulk lookup. """
|
||||
a = AsyncDNS ()
|
||||
a.bulk_query (dict_, rr)
|
||||
a.wait (timeout)
|
||||
a.cancel ()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import netaddr
|
||||
|
||||
queries = dict ()
|
||||
for i in range (64, 64 + 32):
|
||||
ip = '66.249.%d.42' % i # google assigned netblock
|
||||
queries[ip] = None
|
||||
|
||||
bulk_query (queries, adns.rr.PTR)
|
||||
|
||||
ipset = netaddr.IPSet ()
|
||||
for ip in sorted (queries):
|
||||
if queries[ip] and 'proxy' in queries[ip][0]:
|
||||
print (ip)
|
||||
ipset.add (ip + '/24')
|
||||
|
||||
for cidr in ipset.iter_cidrs ():
|
||||
print (cidr)
|
|
@ -0,0 +1,13 @@
|
|||
[Unit]
|
||||
Description=autocat3 Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=autocat
|
||||
Type=simple
|
||||
WorkingDirectory=/var/lib/autocat/autocat3
|
||||
ExecStartPre=-/usr/bin/mkdir /var/run/autocat
|
||||
ExecStart=/usr/local/bin/pipenv run python CherryPyApp.py
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,64 @@
|
|||
sudo yum install git
|
||||
#sudo yum install postgresql-server
|
||||
#sudo yum install postgresql-contrib
|
||||
|
||||
# install py3 (might not be the bast way to do this)
|
||||
|
||||
#sudo yum install centos-release-scl
|
||||
#sudo yum install rh-python36
|
||||
#scl enable rh-python36 bash
|
||||
|
||||
#install pip
|
||||
|
||||
sudo yum groupinstall 'Development Tools'
|
||||
# pip is not on secure_path
|
||||
sudo /opt/rh/rh-python36/root/usr/bin/pip install --upgrade pip
|
||||
sudo /opt/rh/rh-python36/root/usr/bin/pip install pipenv
|
||||
|
||||
# create autocat user with home directory /var/lib/autocat
|
||||
|
||||
sudo useradd -d /var/lib/ autocat
|
||||
sudo passwd autocat
|
||||
sudo su - autocat
|
||||
|
||||
# create ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub using app key from the gutenbergtools/autocat3 repo
|
||||
# id_rsa should have permissions 400
|
||||
mkdir .ssh
|
||||
install -m 600 .ssh/id_rsa
|
||||
touch .ssh/id_rsa.pub
|
||||
#!! from local
|
||||
# scp [local:]~.ssh/github [autocat@host:]~/.ssh/id_rsa
|
||||
# scp [local:]~.ssh/github.pub [autocat@host:]~/.ssh/id_rsa.pub
|
||||
chmod 400 .ssh/id_rsa
|
||||
|
||||
# create ~/.pgpass file to store password in format
|
||||
# [pghost]:*:[pgdatabase]:[pguser]:[password]
|
||||
chmod 400 .pgpass
|
||||
|
||||
#set default python - only needed if pu3 is
|
||||
scl enable rh-python36 bash
|
||||
echo 'source scl_source enable rh-python36' >> /var/lib/autocat/.bash_profile
|
||||
|
||||
git clone git@github.com:gutenbergtools/autocat3.git
|
||||
cd autocat3
|
||||
pipenv --three
|
||||
git checkout remotes/origin/master
|
||||
pipenv install
|
||||
|
||||
# add conf file
|
||||
#!! from local
|
||||
# scp [local:]~/autocat3.conf [autocat@host:]~/.autocat3
|
||||
|
||||
mkdir /var/lib/autocat/log/
|
||||
touch /var/lib/autocat/log/error.log
|
||||
touch /var/lib/autocat/log/access.log
|
||||
|
||||
exit
|
||||
|
||||
sudo mkdir /var/run/autocat
|
||||
sudo touch /var/run/autocat/autocat3.pid
|
||||
sudo chown autocat /var/run/autocat/autocat3.pid
|
||||
|
||||
sudo systemctl enable /var/lib/autocat/autocat3/autocat3.service
|
||||
sudo systemctl start autocat3
|
||||
|
321
ipinfo.py
321
ipinfo.py
|
@ -1,321 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
ipinfo.py
|
||||
|
||||
Copyright 2013-14 by Marcello Perathoner
|
||||
|
||||
Distributable under the GNU General Public License Version 3 or newer.
|
||||
|
||||
Find information about an IP, eg. hostname, whois, DNS blocklists.
|
||||
|
||||
|
||||
The Spamhaus Block List (SBL) Advisory is a database of IP
|
||||
addresses from which Spamhaus does not recommend the acceptance of
|
||||
electronic mail.
|
||||
|
||||
The Spamhaus Exploits Block List (XBL) is a realtime database
|
||||
of IP addresses of hijacked PCs infected by illegal 3rd party
|
||||
exploits, including open proxies (HTTP, socks, AnalogX, wingate,
|
||||
etc), worms/viruses with built-in spam engines, and other types of
|
||||
trojan-horse exploits.
|
||||
|
||||
The Spamhaus PBL is a DNSBL database of end-user IP address
|
||||
ranges which should not be delivering unauthenticated SMTP email
|
||||
to any Internet mail server except those provided for specifically
|
||||
by an ISP for that customer's use. The PBL helps networks enforce
|
||||
their Acceptable Use Policy for dynamic and non-MTA customer IP
|
||||
ranges.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import asyncdns
|
||||
|
||||
# pylint: disable=R0903
|
||||
|
||||
class DNSBL (object):
|
||||
""" Base class for DNS blocklists. """
|
||||
|
||||
zone = ''
|
||||
blackhat_tags = {}
|
||||
dialup_tags = {}
|
||||
|
||||
|
||||
### TOR ###
|
||||
# see:
|
||||
# https://www.torproject.org/projects/tordnsel.html.en
|
||||
# https://www.dan.me.uk/dnsbl
|
||||
|
||||
class TorProject (DNSBL):
|
||||
""" A TOR exitnode list. """
|
||||
|
||||
# note: reverse IP of www.gutenberg.org:80
|
||||
zone = '80.47.134.19.152.ip-port.exitlist.torproject.org'
|
||||
blackhat_tags = {
|
||||
'127.0.0.2': 'TOR',
|
||||
}
|
||||
|
||||
class TorDanme (DNSBL):
|
||||
""" A TOR exitnode list. """
|
||||
|
||||
zone = 'torexit.dan.me.uk'
|
||||
blackhat_tags = {
|
||||
'127.0.0.100': 'TOR',
|
||||
}
|
||||
|
||||
|
||||
### SPAMHAUS ###
|
||||
# see: http://www.spamhaus.org/faq/answers.lasso?section=DNSBL%20Usage#202
|
||||
|
||||
class Spamhaus (DNSBL):
|
||||
""" A DNS blocklist. """
|
||||
|
||||
zone = 'zen.spamhaus.org'
|
||||
blackhat_tags = {
|
||||
'127.0.0.2': 'SPAMHAUS_SBL',
|
||||
'127.0.0.3': 'SPAMHAUS_SBL_CSS',
|
||||
'127.0.0.4': 'SPAMHAUS_XBL_CBL',
|
||||
}
|
||||
dialup_tags = {
|
||||
'127.0.0.10': 'SPAMHAUS_PBL_ISP',
|
||||
'127.0.0.11': 'SPAMHAUS_PBL',
|
||||
}
|
||||
lookup = 'http://www.spamhaus.org/query/ip/{ip}'
|
||||
|
||||
|
||||
### SORBS ###
|
||||
# see: http://www.sorbs.net/using.shtml
|
||||
|
||||
class SORBS (DNSBL):
|
||||
""" A DNS blocklist. """
|
||||
|
||||
zone = 'dnsbl.sorbs.net'
|
||||
blackhat_tags = {
|
||||
'127.0.0.2': 'SORBS_HTTP_PROXY',
|
||||
'127.0.0.3': 'SORBS_SOCKS_PROXY',
|
||||
'127.0.0.4': 'SORBS_MISC_PROXY',
|
||||
'127.0.0.5': 'SORBS_SMTP_RELAY',
|
||||
'127.0.0.6': 'SORBS_SPAMMER',
|
||||
'127.0.0.7': 'SORBS_WEB', # formmail etc.
|
||||
'127.0.0.8': 'SORBS_BLOCK',
|
||||
'127.0.0.9': 'SORBS_ZOMBIE',
|
||||
'127.0.0.11': 'SORBS_BADCONF',
|
||||
'127.0.0.12': 'SORBS_NOMAIL',
|
||||
}
|
||||
dialup_tags = {
|
||||
'127.0.0.10': 'SORBS_DUL',
|
||||
}
|
||||
|
||||
|
||||
### mailspike.net ###
|
||||
# see: http://mailspike.net/usage.html
|
||||
|
||||
class MailSpike (DNSBL):
|
||||
""" A DNS blocklist. """
|
||||
|
||||
zone = 'bl.mailspike.net'
|
||||
blackhat_tags = {
|
||||
'127.0.0.2': 'MAILSPIKE_DISTRIBUTED_SPAM',
|
||||
'127.0.0.10': 'MAILSPIKE_WORST_REPUTATION',
|
||||
'127.0.0.11': 'MAILSPIKE_VERY_BAD_REPUTATION',
|
||||
'127.0.0.12': 'MAILSPIKE_BAD_REPUTATION',
|
||||
}
|
||||
|
||||
|
||||
### shlink.org ###
|
||||
# see: http://shlink.org/
|
||||
|
||||
class BlShlink (DNSBL):
|
||||
""" A DNS blocklist. """
|
||||
|
||||
zone = 'bl.shlink.org'
|
||||
blackhat_tags = {
|
||||
'127.0.0.2': 'SHLINK_SPAM_SENDER',
|
||||
'127.0.0.4': 'SHLINK_SPAM_ORIGINATOR',
|
||||
'127.0.0.5': 'SHLINK_POLICY_BLOCK',
|
||||
'127.0.0.6': 'SHLINK_ATTACKER',
|
||||
}
|
||||
|
||||
class DynShlink (DNSBL):
|
||||
""" A DNS dul list. """
|
||||
|
||||
zone = 'dyn.shlink.org'
|
||||
dialup_tags = {
|
||||
'127.0.0.3': 'SHLINK_DUL',
|
||||
}
|
||||
|
||||
|
||||
### barracudacentral.org ###
|
||||
# see: http://www.barracudacentral.org/rbl/how-to-usee
|
||||
|
||||
class Barracuda (DNSBL):
|
||||
""" A DNS blocklist. """
|
||||
|
||||
zone = 'b.barracudacentral.org'
|
||||
blackhat_tags = {
|
||||
'127.0.0.2': 'BARRACUDA_BLOCK',
|
||||
}
|
||||
|
||||
|
||||
### SHADOWSERVER ###
|
||||
# http://www.shadowserver.org/wiki/pmwiki.php/Services/IP-BGP
|
||||
|
||||
class ShadowServer (DNSBL):
|
||||
""" A DNS-based whois service. """
|
||||
|
||||
zone = 'origin.asn.shadowserver.org'
|
||||
peer_zone = 'peer.asn.shadowserver.org'
|
||||
fields = 'asn cidr org2 country org1 org'.split ()
|
||||
|
||||
|
||||
# TEAMCYMRU
|
||||
# http://www.team-cymru.org/Services/ip-to-asn.html
|
||||
|
||||
class TeamCymru (DNSBL):
|
||||
""" A DNS-based whois service. """
|
||||
|
||||
zone = 'origin.asn.cymru.com'
|
||||
asn_zone = 'asn.cymru.com'
|
||||
fields = 'asn cidr country registry date'.split ()
|
||||
|
||||
|
||||
class IPInfo (object):
|
||||
""" Holds DNSBL information for one IP. """
|
||||
|
||||
dnsbl = [ Spamhaus, SORBS, MailSpike, BlShlink, DynShlink, Barracuda,
|
||||
TorProject, TorDanme ]
|
||||
""" Which blocklists to consider. """
|
||||
|
||||
def __init__ (self, aresolver, ip):
|
||||
self.hostname = None
|
||||
self.whois = {}
|
||||
self.blackhat_tags = set ()
|
||||
self.dialup_tags = set ()
|
||||
|
||||
ip = str (ip)
|
||||
rr = asyncdns.adns.rr
|
||||
|
||||
try:
|
||||
aresolver.query (ip, self._hostnamesetter (), rr.PTR)
|
||||
|
||||
for dnsbl in self.dnsbl:
|
||||
aresolver.query_dnsbl (ip, dnsbl.zone, self._tagsetter (dnsbl))
|
||||
|
||||
# ShadowServer seems down: March 2014
|
||||
aresolver.query_dnsbl (ip, ShadowServer.zone, self._whoissetter_ss (), rr.TXT)
|
||||
# aresolver.query_dnsbl (ip, TeamCymru.zone, self._whoissetter_tc (aresolver), rr.TXT)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@property
|
||||
def tags (self):
|
||||
""" All tags (bad and dialup). """
|
||||
return self.blackhat_tags | self.dialup_tags
|
||||
|
||||
|
||||
def is_blackhat (self):
|
||||
""" Return true if this is probably a blackhat IP. """
|
||||
return bool (self.blackhat_tags)
|
||||
|
||||
|
||||
def is_dialup (self):
|
||||
""" Test if this IP is a dialup. """
|
||||
return bool (self.dialup_tags)
|
||||
|
||||
|
||||
def is_tor_exit (self):
|
||||
""" Test if this is a Tor exit node. """
|
||||
return 'TOR' in self.blackhat_tags
|
||||
|
||||
|
||||
def _hostnamesetter (self):
|
||||
""" Return a callable object that puts the answer into
|
||||
the hostname attribute. """
|
||||
def g (answer):
|
||||
""" Store answer. """
|
||||
self.hostname = answer[0]
|
||||
return g
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _filter (answers, tag_dict):
|
||||
""" Lookup answers in tag_dict, return values of matches. """
|
||||
return [ tag_dict[ip] for ip in answers if ip in tag_dict ]
|
||||
|
||||
|
||||
def _tagsetter (self, dnsbl):
|
||||
""" Return a callable object that puts the answer into
|
||||
our *tags attributes. """
|
||||
def g (answer):
|
||||
""" Store answer. """
|
||||
self.blackhat_tags.update (self._filter (answer, dnsbl.blackhat_tags))
|
||||
self.dialup_tags.update (self._filter (answer, dnsbl.dialup_tags))
|
||||
return g
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _decode_txt (answer):
|
||||
""" Helper: decode / unpack whois answer. """
|
||||
try:
|
||||
answer = answer[0][0].decode ('utf-8')
|
||||
except UnicodeError:
|
||||
answer = answer[0][0].decode ('iso-8859-1')
|
||||
answer = answer.strip ('"').split ('|')
|
||||
return [ a.strip () for a in answer if a ]
|
||||
|
||||
|
||||
def _whoissetter_ss (self):
|
||||
""" Return a callable object that puts the answer into
|
||||
the whois dict. """
|
||||
def g (answer):
|
||||
""" Store answer. """
|
||||
self.whois = dict (zip (ShadowServer.fields, self._decode_txt (answer)))
|
||||
return g
|
||||
|
||||
|
||||
def _whoissetter_tc (self, aresolver):
|
||||
""" Return a callable object that puts the answer into
|
||||
the right attribute. """
|
||||
def g (answer):
|
||||
""" Store answer. """
|
||||
self.whois = dict (zip (TeamCymru.fields, self._decode_txt (answer)))
|
||||
self.whois['org'] = None
|
||||
# maybe there's still more info?
|
||||
aresolver.query ('AS' + self.whois['asn'] + '.' + TeamCymru.asn_zone,
|
||||
self._whoissetter_tc2 (), asyncdns.adns.rr.TXT)
|
||||
return g
|
||||
|
||||
|
||||
def _whoissetter_tc2 (self):
|
||||
""" Return a callable object that puts the answer into
|
||||
the right attribute. """
|
||||
def g (answer):
|
||||
""" Store answer. """
|
||||
self.whois['org'] = self._decode_txt (answer)[-1]
|
||||
return g
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
# test IP 127.0.0.2 should give all positives
|
||||
|
||||
a = asyncdns.AsyncDNS (asyncdns.RESOLV_CONF)
|
||||
i = IPInfo (a, sys.argv[1])
|
||||
a.wait ()
|
||||
a.cancel ()
|
||||
|
||||
print ('hostname: %s' % i.hostname)
|
||||
for k in sorted (i.whois.keys ()):
|
||||
print ("%s: %s" % (k, i.whois[k]))
|
||||
for tag in sorted (i.tags):
|
||||
print (tag)
|
||||
if i.is_blackhat ():
|
||||
print ('BLACKHAT')
|
||||
if i.is_dialup ():
|
||||
print ('DUL')
|
|
@ -123,7 +123,6 @@
|
|||
|
||||
<td rowspan="2" id="logo" i18n:comment="The PG logo at the top left of every page.">
|
||||
<a href="/wiki/Main_Page" title="Go to the Main Page.">
|
||||
<span id="${cherrypy.tools.rate_limiter.get_challenge ()}" class="icon icon_logo" />
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
<div class="table link">
|
||||
<div class="row">
|
||||
<div class="cell leftcell">
|
||||
<div class="icon icon_search" id="${cherrypy.tools.rate_limiter.get_challenge ()}" />
|
||||
</div>
|
||||
<div class="cell content">
|
||||
<form id="search" method="get" action="${os.mobile_search}"
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:py="http://genshi.edgewall.org/"
|
||||
xmlns:i18n="http://genshi.edgewall.org/i18n"
|
||||
xml:lang="en">
|
||||
|
||||
<!--! xml:lang avoids extraction for translation -->
|
||||
|
||||
<?python
|
||||
from libgutenberg.GutenbergGlobals import xmlspecialchars as esc
|
||||
?>
|
||||
|
||||
<py:def function="print_session">
|
||||
<?python
|
||||
from __future__ import unicode_literals
|
||||
|
||||
hostname = ''
|
||||
whois = ''
|
||||
tags = []
|
||||
bad_tags = []
|
||||
|
||||
ips = d.ips
|
||||
info = ips.ipinfo
|
||||
if info is not None:
|
||||
hostname = info.hostname
|
||||
whois = ' - '.join (filter (None, info.whois.values ()))
|
||||
if info.is_dialup ():
|
||||
tags.append ('DUL')
|
||||
bad_tags = sorted (info.tags & info.blackhat_tags)
|
||||
|
||||
if d['blocked'] == 9:
|
||||
tags.append ('->DB')
|
||||
if d['css_ok'] == False:
|
||||
bad_tags.append ('NO_CSS')
|
||||
session_cnt = len (d.sessions)
|
||||
?>
|
||||
<span class='ip'>${str (ips)}</span>
|
||||
-
|
||||
<span class='hits'>${d['hits']}</span> hits
|
||||
<span py:if="d['dhits'] > 0"><span class='dhits'>${d['dhits']}</span> denied</span>
|
||||
<span class='rhits'>(${d['rhits']}/${d['rhits_max']})</span>
|
||||
<span py:if='session_cnt > 1' class='sessions'>${session_cnt} sess.</span>
|
||||
<span class='host'>${hostname}</span>
|
||||
<span class='tags'>${' '.join (sorted (tags))}</span>
|
||||
<span class='bad_tags'>${' '.join (sorted (bad_tags))}</span>
|
||||
<span class='whois'>${whois}</span>
|
||||
<span class="ua">${' -- '.join (sorted (
|
||||
[rl.ua_decode (ua) for ua in d['user_agents']]
|
||||
))[:1000]}</span>
|
||||
<span class="ua-sig">${' -- '.join (sorted (
|
||||
[rl.ua_decode (sig) for sig in d['signatures']]
|
||||
))[:1000]}</span>
|
||||
<a href="/webmaster/stats/block/?ip=${ips.get_ip_to_block ()}">block</a>
|
||||
<a href="/webmaster/stats/unblock/?ip=${ips.get_ip_to_block ()}">unblock</a>
|
||||
</py:def>
|
||||
|
||||
<py:def function="print_requests">
|
||||
<ul class="requests">
|
||||
<li py:for="request in d['requests']">${request}</li>
|
||||
</ul>
|
||||
</py:def>
|
||||
|
||||
<head>
|
||||
<title>AppServer Status</title>
|
||||
<style type="text/css">
|
||||
.ip { font-weight: bold }
|
||||
.hits { font-weight: bold }
|
||||
.dhits { font-weight: bold; color: red }
|
||||
.rhits { color: blue }
|
||||
.host { font-weight: bold }
|
||||
.sessions { font-weight: bold; color: red }
|
||||
.whois { color: grey }
|
||||
.tags { font-weight: bold; color: green }
|
||||
.bad_tags { font-weight: bold; color: red }
|
||||
.ua { color: blue }
|
||||
.ua-sig { color: #808 }
|
||||
.requests { list-style-type: none; font-size: small; color: grey }
|
||||
.requests li { display: inline }
|
||||
.requests li:before { content: ' - ' }
|
||||
.whitelisted { color: green }
|
||||
.nagios { display: none }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Stats</h1>
|
||||
|
||||
<p>
|
||||
RHits Max: ${rl.rhits_max}.
|
||||
Captchas: ${rl.captchas_max}.
|
||||
Cleanup Frequency: ${rl.frequency}s.
|
||||
</p>
|
||||
<p>Active Users: ${rl.users}</p>
|
||||
<p>Hits: ${rl.hits}</p>
|
||||
<p>Whitelisted: ${rl.whitelist_hits}</p>
|
||||
<p>Denied: ${rl.denied_hits}</p>
|
||||
<p>Blocked IPs: ${len (blocked)}</p>
|
||||
<p>Total Backends: ${backends}</p>
|
||||
<p>Active Backends: ${active_backends}</p>
|
||||
|
||||
<p>Formats Sum:</p>
|
||||
|
||||
<table>
|
||||
<tr py:for="key, value, percent in bs.formats_sum_acc.iter_results ()">
|
||||
<td>${key}</td><td>${value}</td><td>${"%.3f" % percent}</td>
|
||||
<td class="nagios">nagios-${key}-sum: ${value} ${"%.3f" % percent}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Formats Detail:</p>
|
||||
|
||||
<table>
|
||||
<tr py:for="key, value, percent in bs.formats_acc.iter_results ()">
|
||||
<td>${key}</td><td>${value}</td><td>${"%.3f" % percent}</td>
|
||||
<td class="nagios">nagios-${key}: ${value} ${"%.3f" % percent}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<py:if test="resolve">
|
||||
|
||||
<p>Blocked IPs:</p>
|
||||
|
||||
<ul>
|
||||
<!--! the blocked IPs sorted by IP -->
|
||||
<li py:for="d in blocked">
|
||||
${print_session ()}
|
||||
${print_requests ()}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Busiest IPs:</p>
|
||||
|
||||
<ul>
|
||||
<!--! the top 10 active IPs sorted by hits desc -->
|
||||
<li py:for="d in busiest" class="${'whitelisted' if d.ips.whitelisted else ''}">
|
||||
${print_session ()}
|
||||
${print_requests ()}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>IPs with most sessions:</p>
|
||||
|
||||
<ul>
|
||||
<!--! the top 10 IPs with most sessions sorted by sessions desc -->
|
||||
<li py:for="d in most_sessions" class="${'whitelisted' if d.ips.whitelisted else ''}">
|
||||
${print_session ()}
|
||||
${print_requests ()}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Active IPs: ${len (active)}</p>
|
||||
|
||||
<ul>
|
||||
<!--! the active IPs sorted by IP -->
|
||||
<li py:for="d in active" class="${'whitelisted' if d.ips.whitelisted else ''}">
|
||||
${print_session ()}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</py:if> <!--! resolve -->
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue