Initial commit

This commit is contained in:
Christopher Puschmann 2017-12-16 01:08:45 +01:00
commit e48ae45ca1
22 changed files with 3682 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node/node_modules/*
.idea/

22
README.md Normal file
View File

@ -0,0 +1,22 @@
# Selfhosting Trashmail API
Basic self hosting trashmail API using docker NodeJS, Redis, NGINX + LUA
Requirements
---
* Docker
* [Docker-Compose](https://docs.docker.com/compose/)
Installation
---
You need to set permissions right to allow npm to run `npm install`
```
chmod -R 777 node
docker-compose up
```
Use the `-d` option to run the containers in daemon mode, and `docker-compose logs -f` to watch logs

27
docker-compose.yml Normal file
View File

@ -0,0 +1,27 @@
version: '3'
services:
node:
image: node:9.2.0-alpine
user: node
working_dir: /home/node/app
volumes:
- ./node/:/home/node/app
command: /bin/sh -c "npm i && node ."
depends_on:
- redis
redis:
image: redis:3.2.11-alpine
restart: always
ports:
- 6379:6379
nginx:
image: registry.lumen.sh/lumen/docker-alpine-nginx-lua:1.13.7
volumes:
- ./nginx/conf/:/etc/nginx
- ./nginx/lua/:/etc/nginx/lua
restart: always
depends_on:
- redis
ports:
- 80:80

109
nginx/conf/koi-utf Normal file
View File

@ -0,0 +1,109 @@
# This map is not a full koi8-r <> utf8 map: it does not contain
# box-drawing and some other characters. Besides this map contains
# several koi8-u and Byelorussian letters which are not in koi8-r.
# If you need a full and standard map, use contrib/unicode2nginx/koi-utf
# map instead.
charset_map koi8-r utf-8 {
80 E282AC ; # euro
95 E280A2 ; # bullet
9A C2A0 ; # &nbsp;
9E C2B7 ; # &middot;
A3 D191 ; # small yo
A4 D194 ; # small Ukrainian ye
A6 D196 ; # small Ukrainian i
A7 D197 ; # small Ukrainian yi
AD D291 ; # small Ukrainian soft g
AE D19E ; # small Byelorussian short u
B0 C2B0 ; # &deg;
B3 D081 ; # capital YO
B4 D084 ; # capital Ukrainian YE
B6 D086 ; # capital Ukrainian I
B7 D087 ; # capital Ukrainian YI
B9 E28496 ; # numero sign
BD D290 ; # capital Ukrainian soft G
BE D18E ; # capital Byelorussian short U
BF C2A9 ; # (C)
C0 D18E ; # small yu
C1 D0B0 ; # small a
C2 D0B1 ; # small b
C3 D186 ; # small ts
C4 D0B4 ; # small d
C5 D0B5 ; # small ye
C6 D184 ; # small f
C7 D0B3 ; # small g
C8 D185 ; # small kh
C9 D0B8 ; # small i
CA D0B9 ; # small j
CB D0BA ; # small k
CC D0BB ; # small l
CD D0BC ; # small m
CE D0BD ; # small n
CF D0BE ; # small o
D0 D0BF ; # small p
D1 D18F ; # small ya
D2 D180 ; # small r
D3 D181 ; # small s
D4 D182 ; # small t
D5 D183 ; # small u
D6 D0B6 ; # small zh
D7 D0B2 ; # small v
D8 D18C ; # small soft sign
D9 D18B ; # small y
DA D0B7 ; # small z
DB D188 ; # small sh
DC D18D ; # small e
DD D189 ; # small shch
DE D187 ; # small ch
DF D18A ; # small hard sign
E0 D0AE ; # capital YU
E1 D090 ; # capital A
E2 D091 ; # capital B
E3 D0A6 ; # capital TS
E4 D094 ; # capital D
E5 D095 ; # capital YE
E6 D0A4 ; # capital F
E7 D093 ; # capital G
E8 D0A5 ; # capital KH
E9 D098 ; # capital I
EA D099 ; # capital J
EB D09A ; # capital K
EC D09B ; # capital L
ED D09C ; # capital M
EE D09D ; # capital N
EF D09E ; # capital O
F0 D09F ; # capital P
F1 D0AF ; # capital YA
F2 D0A0 ; # capital R
F3 D0A1 ; # capital S
F4 D0A2 ; # capital T
F5 D0A3 ; # capital U
F6 D096 ; # capital ZH
F7 D092 ; # capital V
F8 D0AC ; # capital soft sign
F9 D0AB ; # capital Y
FA D097 ; # capital Z
FB D0A8 ; # capital SH
FC D0AD ; # capital E
FD D0A9 ; # capital SHCH
FE D0A7 ; # capital CH
FF D0AA ; # capital hard sign
}

103
nginx/conf/koi-win Normal file
View File

@ -0,0 +1,103 @@
charset_map koi8-r windows-1251 {
80 88 ; # euro
95 95 ; # bullet
9A A0 ; # &nbsp;
9E B7 ; # &middot;
A3 B8 ; # small yo
A4 BA ; # small Ukrainian ye
A6 B3 ; # small Ukrainian i
A7 BF ; # small Ukrainian yi
AD B4 ; # small Ukrainian soft g
AE A2 ; # small Byelorussian short u
B0 B0 ; # &deg;
B3 A8 ; # capital YO
B4 AA ; # capital Ukrainian YE
B6 B2 ; # capital Ukrainian I
B7 AF ; # capital Ukrainian YI
B9 B9 ; # numero sign
BD A5 ; # capital Ukrainian soft G
BE A1 ; # capital Byelorussian short U
BF A9 ; # (C)
C0 FE ; # small yu
C1 E0 ; # small a
C2 E1 ; # small b
C3 F6 ; # small ts
C4 E4 ; # small d
C5 E5 ; # small ye
C6 F4 ; # small f
C7 E3 ; # small g
C8 F5 ; # small kh
C9 E8 ; # small i
CA E9 ; # small j
CB EA ; # small k
CC EB ; # small l
CD EC ; # small m
CE ED ; # small n
CF EE ; # small o
D0 EF ; # small p
D1 FF ; # small ya
D2 F0 ; # small r
D3 F1 ; # small s
D4 F2 ; # small t
D5 F3 ; # small u
D6 E6 ; # small zh
D7 E2 ; # small v
D8 FC ; # small soft sign
D9 FB ; # small y
DA E7 ; # small z
DB F8 ; # small sh
DC FD ; # small e
DD F9 ; # small shch
DE F7 ; # small ch
DF FA ; # small hard sign
E0 DE ; # capital YU
E1 C0 ; # capital A
E2 C1 ; # capital B
E3 D6 ; # capital TS
E4 C4 ; # capital D
E5 C5 ; # capital YE
E6 D4 ; # capital F
E7 C3 ; # capital G
E8 D5 ; # capital KH
E9 C8 ; # capital I
EA C9 ; # capital J
EB CA ; # capital K
EC CB ; # capital L
ED CC ; # capital M
EE CD ; # capital N
EF CE ; # capital O
F0 CF ; # capital P
F1 DF ; # capital YA
F2 D0 ; # capital R
F3 D1 ; # capital S
F4 D2 ; # capital T
F5 D3 ; # capital U
F6 C6 ; # capital ZH
F7 C2 ; # capital V
F8 DC ; # capital soft sign
F9 DB ; # capital Y
FA C7 ; # capital Z
FB D8 ; # capital SH
FC DD ; # capital E
FD D9 ; # capital SHCH
FE D7 ; # capital CH
FF DA ; # capital hard sign
}

1
nginx/conf/modules Symbolic link
View File

@ -0,0 +1 @@
../../usr/lib/nginx/modules

48
nginx/conf/nginx.conf Normal file
View File

@ -0,0 +1,48 @@
#user nobody;
worker_processes auto;
worker_rlimit_nofile 100000;
error_log /var/log/nginx/error.log;
events {
worker_connections 65535;
use epoll;
multi_accept on;
}
http {
access_log off;
resolver 127.0.0.11 ipv6=off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 30;
client_header_timeout 10;
client_body_timeout 10;
send_timeout 10;
server_tokens off;
lua_package_path '/etc/nginx/lua/modules/?.lua;;';
lua_socket_log_errors off;
server {
listen 80;
server_name _;
location ~ ^/(check|10minutemail|disposable)/(raw|json|xml|status)$ {
add_header X-Request-Id $request_id;
content_by_lua_file lua/mail.lua;
}
location ~ ^/(validate|valid)/(raw|json|xml|status)$ {
if ($request_method != POST) {
return 400;
}
content_by_lua_file lua/validator.lua;
}
}
}

123
nginx/conf/on Normal file
View File

@ -0,0 +1,123 @@
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/mysql/admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/mysql/dbadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/mysql/sqlmanager/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/mysql/mysqlmanager/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/phpmyadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/phpMyadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/phpMyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/phpmyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:31 +0000] "HEAD http://178.62.212.150:80/phpmyadmin3/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/phpmyadmin4/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/2phpmyadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/phpmy/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/phppma/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/myadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/shopdb/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/MyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/program/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/PMA/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/dbadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/pma/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/db/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/mysql/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/database/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:32 +0000] "HEAD http://178.62.212.150:80/db/phpmyadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/db/phpMyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/sqlmanager/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/mysqlmanager/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/php-myadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/phpmy-admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/mysqladmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/mysql-admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/phpmyadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/phpMyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/sysadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/sqladmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/db/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/web/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/admin/pMA/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:33 +0000] "HEAD http://178.62.212.150:80/mysql/pma/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/mysql/db/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/mysql/web/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/mysql/pMA/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/phpmanager/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/php-myadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/phpmy-admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/sql/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/myadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/webadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/sqlweb/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/websql/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/webdb/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/sqladmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/sql-admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/phpmyadmin2/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:34 +0000] "HEAD http://178.62.212.150:80/sql/phpMyAdmin2/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/sql/phpMyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/myadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/webadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/dbweb/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/websql/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/webdb/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/dbadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/db-admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/phpmyadmin3/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/phpMyAdmin3/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/db/phpMyAdmin-3/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/phpmyadmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/phpMyAdmin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/db/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/web/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/pma/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/PMA/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:35 +0000] "HEAD http://178.62.212.150:80/administrator/admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/phpMyAdmin2/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/phpMyAdmin3/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/phpMyAdmin4/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/phpMyAdmin-3/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/php-my-admin/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2011/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2012/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2013/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2014/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2015/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2016/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2017/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/PMA2018/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/pma2011/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/pma2012/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/pma2013/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/pma2014/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:36 +0000] "HEAD http://178.62.212.150:80/pma2015/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/pma2016/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/pma2017/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/pma2018/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2011/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2012/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2013/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2014/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2016/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:37 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2017/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:38 +0000] "HEAD http://178.62.212.150:80/phpmyadmin2018/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
2.82.138.16 - - [06/Dec/2017:16:14:38 +0000] "HEAD http://178.62.212.150:80/phpmanager/ HTTP/1.1" 404 0 "-" "Mozilla/5.0 Jorgee"
37.58.58.232 - - [06/Dec/2017:17:20:13 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:21:27 +0000] "POST /check/json/test HTTP/1.1" 200 71 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:21:31 +0000] "POST /check/json/test HTTP/1.1" 200 71 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:21:43 +0000] "POST /check/json/test HTTP/1.1" 400 166 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:21:49 +0000] "POST /check/json/test HTTP/1.1" 200 69 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:25:27 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:25:48 +0000] "POST /check/json/test HTTP/1.1" 200 69 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:39:34 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:39:43 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:40:10 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:40:15 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:41:01 +0000] "POST /check/json/test HTTP/1.1" 503 206 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:41:07 +0000] "POST /check/json/test HTTP/1.1" 503 206 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:41:11 +0000] "POST /check/json/test HTTP/1.1" 503 206 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:41:32 +0000] "POST /check/json/test HTTP/1.1" 503 206 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:43:20 +0000] "POST /check/json/test HTTP/1.1" 200 69 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:46:09 +0000] "POST /check/json/test HTTP/1.1" 500 186 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:46:50 +0000] "POST /check/json/test HTTP/1.1" 200 69 "-" "PostmanRuntime/6.3.2"
37.58.58.232 - - [06/Dec/2017:17:54:31 +0000] "POST /check/json/test HTTP/1.1" 200 69 "-" "PostmanRuntime/6.3.2"

126
nginx/conf/win-utf Normal file
View File

@ -0,0 +1,126 @@
# This map is not a full windows-1251 <> utf8 map: it does not
# contain Serbian and Macedonian letters. If you need a full map,
# use contrib/unicode2nginx/win-utf map instead.
charset_map windows-1251 utf-8 {
82 E2809A ; # single low-9 quotation mark
84 E2809E ; # double low-9 quotation mark
85 E280A6 ; # ellipsis
86 E280A0 ; # dagger
87 E280A1 ; # double dagger
88 E282AC ; # euro
89 E280B0 ; # per mille
91 E28098 ; # left single quotation mark
92 E28099 ; # right single quotation mark
93 E2809C ; # left double quotation mark
94 E2809D ; # right double quotation mark
95 E280A2 ; # bullet
96 E28093 ; # en dash
97 E28094 ; # em dash
99 E284A2 ; # trade mark sign
A0 C2A0 ; # &nbsp;
A1 D18E ; # capital Byelorussian short U
A2 D19E ; # small Byelorussian short u
A4 C2A4 ; # currency sign
A5 D290 ; # capital Ukrainian soft G
A6 C2A6 ; # borken bar
A7 C2A7 ; # section sign
A8 D081 ; # capital YO
A9 C2A9 ; # (C)
AA D084 ; # capital Ukrainian YE
AB C2AB ; # left-pointing double angle quotation mark
AC C2AC ; # not sign
AD C2AD ; # soft hypen
AE C2AE ; # (R)
AF D087 ; # capital Ukrainian YI
B0 C2B0 ; # &deg;
B1 C2B1 ; # plus-minus sign
B2 D086 ; # capital Ukrainian I
B3 D196 ; # small Ukrainian i
B4 D291 ; # small Ukrainian soft g
B5 C2B5 ; # micro sign
B6 C2B6 ; # pilcrow sign
B7 C2B7 ; # &middot;
B8 D191 ; # small yo
B9 E28496 ; # numero sign
BA D194 ; # small Ukrainian ye
BB C2BB ; # right-pointing double angle quotation mark
BF D197 ; # small Ukrainian yi
C0 D090 ; # capital A
C1 D091 ; # capital B
C2 D092 ; # capital V
C3 D093 ; # capital G
C4 D094 ; # capital D
C5 D095 ; # capital YE
C6 D096 ; # capital ZH
C7 D097 ; # capital Z
C8 D098 ; # capital I
C9 D099 ; # capital J
CA D09A ; # capital K
CB D09B ; # capital L
CC D09C ; # capital M
CD D09D ; # capital N
CE D09E ; # capital O
CF D09F ; # capital P
D0 D0A0 ; # capital R
D1 D0A1 ; # capital S
D2 D0A2 ; # capital T
D3 D0A3 ; # capital U
D4 D0A4 ; # capital F
D5 D0A5 ; # capital KH
D6 D0A6 ; # capital TS
D7 D0A7 ; # capital CH
D8 D0A8 ; # capital SH
D9 D0A9 ; # capital SHCH
DA D0AA ; # capital hard sign
DB D0AB ; # capital Y
DC D0AC ; # capital soft sign
DD D0AD ; # capital E
DE D0AE ; # capital YU
DF D0AF ; # capital YA
E0 D0B0 ; # small a
E1 D0B1 ; # small b
E2 D0B2 ; # small v
E3 D0B3 ; # small g
E4 D0B4 ; # small d
E5 D0B5 ; # small ye
E6 D0B6 ; # small zh
E7 D0B7 ; # small z
E8 D0B8 ; # small i
E9 D0B9 ; # small j
EA D0BA ; # small k
EB D0BB ; # small l
EC D0BC ; # small m
ED D0BD ; # small n
EE D0BE ; # small o
EF D0BF ; # small p
F0 D180 ; # small r
F1 D181 ; # small s
F2 D182 ; # small t
F3 D183 ; # small u
F4 D184 ; # small f
F5 D185 ; # small kh
F6 D186 ; # small ts
F7 D187 ; # small ch
F8 D188 ; # small sh
F9 D189 ; # small shch
FA D18A ; # small hard sign
FB D18B ; # small y
FC D18C ; # small soft sign
FD D18D ; # small e
FE D18E ; # small yu
FF D18F ; # small ya
}

38
nginx/lua/mail.lua Normal file
View File

@ -0,0 +1,38 @@
local request = require 'request'
local response = require 'response'
local helper = require 'helper'
local request_uri
local response_type
local domain
local result
local err
local red = helper.redis.connect()
request_uri = helper.parseURL()
if type(request_uri) ~= "table" or table.getn(request_uri) < 2 then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
local response_type = request_uri[2]
if not response.isValidResponseType(response_type) then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
local data = request.getPostData()
if data == nil or data['email'] == nil then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
domain = helper.getDomain(data['email'])
if not domain then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
result = helper.redis.checkDomain(red, 'disposable', domain)
response.createResponse(response_type, data['email'], domain, result)

981
nginx/lua/modules/dns.lua Normal file
View File

@ -0,0 +1,981 @@
-- Copyright (C) Yichun Zhang (agentzh)
-- local socket = require "socket"
local bit = require "bit"
local udp = ngx.socket.udp
local rand = math.random
local char = string.char
local byte = string.byte
local find = string.find
local gsub = string.gsub
local sub = string.sub
local rep = string.rep
local format = string.format
local band = bit.band
local rshift = bit.rshift
local lshift = bit.lshift
local insert = table.insert
local concat = table.concat
local re_sub = ngx.re.sub
local tcp = ngx.socket.tcp
local log = ngx.log
local DEBUG = ngx.DEBUG
local unpack = unpack
local setmetatable = setmetatable
local type = type
local ipairs = ipairs
local ok, new_tab = pcall(require, "table.new")
if not ok then
new_tab = function (narr, nrec) return {} end
end
local DOT_CHAR = byte(".")
local ZERO_CHAR = byte("0")
local COLON_CHAR = byte(":")
local IP6_ARPA = "ip6.arpa"
local TYPE_A = 1
local TYPE_NS = 2
local TYPE_CNAME = 5
local TYPE_SOA = 6
local TYPE_PTR = 12
local TYPE_MX = 15
local TYPE_TXT = 16
local TYPE_AAAA = 28
local TYPE_SRV = 33
local TYPE_SPF = 99
local CLASS_IN = 1
local SECTION_AN = 1
local SECTION_NS = 2
local SECTION_AR = 3
local _M = {
_VERSION = '0.21',
TYPE_A = TYPE_A,
TYPE_NS = TYPE_NS,
TYPE_CNAME = TYPE_CNAME,
TYPE_SOA = TYPE_SOA,
TYPE_PTR = TYPE_PTR,
TYPE_MX = TYPE_MX,
TYPE_TXT = TYPE_TXT,
TYPE_AAAA = TYPE_AAAA,
TYPE_SRV = TYPE_SRV,
TYPE_SPF = TYPE_SPF,
CLASS_IN = CLASS_IN,
SECTION_AN = SECTION_AN,
SECTION_NS = SECTION_NS,
SECTION_AR = SECTION_AR
}
local resolver_errstrs = {
"format error", -- 1
"server failure", -- 2
"name error", -- 3
"not implemented", -- 4
"refused", -- 5
}
local soa_int32_fields = { "serial", "refresh", "retry", "expire", "minimum" }
local mt = { __index = _M }
local arpa_tmpl = new_tab(72, 0)
for i = 1, #IP6_ARPA do
arpa_tmpl[64 + i] = byte(IP6_ARPA, i)
end
for i = 2, 64, 2 do
arpa_tmpl[i] = DOT_CHAR
end
function _M.new(class, opts)
if not opts then
return nil, "no options table specified"
end
local servers = opts.nameservers
if not servers or #servers == 0 then
return nil, "no nameservers specified"
end
local timeout = opts.timeout or 2000 -- default 2 sec
local n = #servers
local socks = {}
for i = 1, n do
local server = servers[i]
local sock, err = udp()
if not sock then
return nil, "failed to create udp socket: " .. err
end
local host, port
if type(server) == 'table' then
host = server[1]
port = server[2] or 53
else
host = server
port = 53
servers[i] = {host, port}
end
local ok, err = sock:setpeername(host, port)
if not ok then
return nil, "failed to set peer name: " .. err
end
sock:settimeout(timeout)
insert(socks, sock)
end
local tcp_sock, err = tcp()
if not tcp_sock then
return nil, "failed to create tcp socket: " .. err
end
tcp_sock:settimeout(timeout)
return setmetatable(
{ cur = rand(1, n), socks = socks,
tcp_sock = tcp_sock,
servers = servers,
retrans = opts.retrans or 5,
no_recurse = opts.no_recurse,
}, mt)
end
local function pick_sock(self, socks)
local cur = self.cur
if cur == #socks then
self.cur = 1
else
self.cur = cur + 1
end
return socks[cur]
end
local function _get_cur_server(self)
local cur = self.cur
local servers = self.servers
if cur == 1 then
return servers[#servers]
end
return servers[cur - 1]
end
function _M.set_timeout(self, timeout)
local socks = self.socks
if not socks then
return nil, "not initialized"
end
for i = 1, #socks do
local sock = socks[i]
sock:settimeout(timeout)
end
local tcp_sock = self.tcp_sock
if not tcp_sock then
return nil, "not initialized"
end
tcp_sock:settimeout(timeout)
end
local function _encode_name(s)
return char(#s) .. s
end
local function _decode_name(buf, pos)
local labels = {}
local nptrs = 0
local p = pos
while nptrs < 128 do
local fst = byte(buf, p)
if not fst then
return nil, 'truncated';
end
-- print("fst at ", p, ": ", fst)
if fst == 0 then
if nptrs == 0 then
pos = pos + 1
end
break
end
if band(fst, 0xc0) ~= 0 then
-- being a pointer
if nptrs == 0 then
pos = pos + 2
end
nptrs = nptrs + 1
local snd = byte(buf, p + 1)
if not snd then
return nil, 'truncated'
end
p = lshift(band(fst, 0x3f), 8) + snd + 1
-- print("resolving ptr ", p, ": ", byte(buf, p))
else
-- being a label
local label = sub(buf, p + 1, p + fst)
insert(labels, label)
-- print("resolved label ", label)
p = p + fst + 1
if nptrs == 0 then
pos = p
end
end
end
return concat(labels, "."), pos
end
local function _build_request(qname, id, no_recurse, opts)
local qtype
if opts then
qtype = opts.qtype
end
if not qtype then
qtype = 1 -- A record
end
local ident_hi = char(rshift(id, 8))
local ident_lo = char(band(id, 0xff))
local flags
if no_recurse then
-- print("found no recurse")
flags = "\0\0"
else
flags = "\1\0"
end
local nqs = "\0\1"
local nan = "\0\0"
local nns = "\0\0"
local nar = "\0\0"
local typ = char(rshift(qtype, 8), band(qtype, 0xff))
local class = "\0\1" -- the Internet class
if byte(qname, 1) == DOT_CHAR then
return nil, "bad name"
end
local name = gsub(qname, "([^.]+)%.?", _encode_name) .. '\0'
return {
ident_hi, ident_lo, flags, nqs, nan, nns, nar,
name, typ, class
}
end
local function parse_section(answers, section, buf, start_pos, size,
should_skip)
local pos = start_pos
for _ = 1, size do
-- print(format("ans %d: qtype:%d qclass:%d", i, qtype, qclass))
local ans = {}
if not should_skip then
insert(answers, ans)
end
ans.section = section
local name
name, pos = _decode_name(buf, pos)
if not name then
return nil, pos
end
ans.name = name
-- print("name: ", name)
local type_hi = byte(buf, pos)
local type_lo = byte(buf, pos + 1)
local typ = lshift(type_hi, 8) + type_lo
ans.type = typ
-- print("type: ", typ)
local class_hi = byte(buf, pos + 2)
local class_lo = byte(buf, pos + 3)
local class = lshift(class_hi, 8) + class_lo
ans.class = class
-- print("class: ", class)
local byte_1, byte_2, byte_3, byte_4 = byte(buf, pos + 4, pos + 7)
local ttl = lshift(byte_1, 24) + lshift(byte_2, 16)
+ lshift(byte_3, 8) + byte_4
-- print("ttl: ", ttl)
ans.ttl = ttl
local len_hi = byte(buf, pos + 8)
local len_lo = byte(buf, pos + 9)
local len = lshift(len_hi, 8) + len_lo
-- print("record len: ", len)
pos = pos + 10
if typ == TYPE_A then
if len ~= 4 then
return nil, "bad A record value length: " .. len
end
local addr_bytes = { byte(buf, pos, pos + 3) }
local addr = concat(addr_bytes, ".")
-- print("ipv4 address: ", addr)
ans.address = addr
pos = pos + 4
elseif typ == TYPE_CNAME then
local cname, p = _decode_name(buf, pos)
if not cname then
return nil, pos
end
if p - pos ~= len then
return nil, format("bad cname record length: %d ~= %d",
p - pos, len)
end
pos = p
-- print("cname: ", cname)
ans.cname = cname
elseif typ == TYPE_AAAA then
if len ~= 16 then
return nil, "bad AAAA record value length: " .. len
end
local addr_bytes = { byte(buf, pos, pos + 15) }
local flds = {}
for i = 1, 16, 2 do
local a = addr_bytes[i]
local b = addr_bytes[i + 1]
if a == 0 then
insert(flds, format("%x", b))
else
insert(flds, format("%x%02x", a, b))
end
end
-- we do not compress the IPv6 addresses by default
-- due to performance considerations
ans.address = concat(flds, ":")
pos = pos + 16
elseif typ == TYPE_MX then
-- print("len = ", len)
if len < 3 then
return nil, "bad MX record value length: " .. len
end
local pref_hi = byte(buf, pos)
local pref_lo = byte(buf, pos + 1)
ans.preference = lshift(pref_hi, 8) + pref_lo
local host, p = _decode_name(buf, pos + 2)
if not host then
return nil, pos
end
if p - pos ~= len then
return nil, format("bad cname record length: %d ~= %d",
p - pos, len)
end
ans.exchange = host
pos = p
elseif typ == TYPE_SRV then
if len < 7 then
return nil, "bad SRV record value length: " .. len
end
local prio_hi = byte(buf, pos)
local prio_lo = byte(buf, pos + 1)
ans.priority = lshift(prio_hi, 8) + prio_lo
local weight_hi = byte(buf, pos + 2)
local weight_lo = byte(buf, pos + 3)
ans.weight = lshift(weight_hi, 8) + weight_lo
local port_hi = byte(buf, pos + 4)
local port_lo = byte(buf, pos + 5)
ans.port = lshift(port_hi, 8) + port_lo
local name, p = _decode_name(buf, pos + 6)
if not name then
return nil, pos
end
if p - pos ~= len then
return nil, format("bad srv record length: %d ~= %d",
p - pos, len)
end
ans.target = name
pos = p
elseif typ == TYPE_NS then
local name, p = _decode_name(buf, pos)
if not name then
return nil, pos
end
if p - pos ~= len then
return nil, format("bad cname record length: %d ~= %d",
p - pos, len)
end
pos = p
-- print("name: ", name)
ans.nsdname = name
elseif typ == TYPE_TXT or typ == TYPE_SPF then
local key = (typ == TYPE_TXT) and "txt" or "spf"
local slen = byte(buf, pos)
if slen + 1 > len then
-- truncate the over-run TXT record data
slen = len
end
-- print("slen: ", len)
local val = sub(buf, pos + 1, pos + slen)
local last = pos + len
pos = pos + slen + 1
if pos < last then
-- more strings to be processed
-- this code path is usually cold, so we do not
-- merge the following loop on this code path
-- with the processing logic above.
val = {val}
local idx = 2
repeat
local slen = byte(buf, pos)
if pos + slen + 1 > last then
-- truncate the over-run TXT record data
slen = last - pos - 1
end
val[idx] = sub(buf, pos + 1, pos + slen)
idx = idx + 1
pos = pos + slen + 1
until pos >= last
end
ans[key] = val
elseif typ == TYPE_PTR then
local name, p = _decode_name(buf, pos)
if not name then
return nil, pos
end
if p - pos ~= len then
return nil, format("bad cname record length: %d ~= %d",
p - pos, len)
end
pos = p
-- print("name: ", name)
ans.ptrdname = name
elseif typ == TYPE_SOA then
local name, p = _decode_name(buf, pos)
if not name then
return nil, pos
end
ans.mname = name
pos = p
name, p = _decode_name(buf, pos)
if not name then
return nil, pos
end
ans.rname = name
for _, field in ipairs(soa_int32_fields) do
local byte_1, byte_2, byte_3, byte_4 = byte(buf, p, p + 3)
ans[field] = lshift(byte_1, 24) + lshift(byte_2, 16)
+ lshift(byte_3, 8) + byte_4
p = p + 4
end
pos = p
else
-- for unknown types, just forward the raw value
ans.rdata = sub(buf, pos, pos + len - 1)
pos = pos + len
end
end
return pos
end
local function parse_response(buf, id, opts)
local n = #buf
if n < 12 then
return nil, 'truncated';
end
-- header layout: ident flags nqs nan nns nar
local ident_hi = byte(buf, 1)
local ident_lo = byte(buf, 2)
local ans_id = lshift(ident_hi, 8) + ident_lo
-- print("id: ", id, ", ans id: ", ans_id)
if ans_id ~= id then
-- identifier mismatch and throw it away
log(DEBUG, "id mismatch in the DNS reply: ", ans_id, " ~= ", id)
return nil, "id mismatch"
end
local flags_hi = byte(buf, 3)
local flags_lo = byte(buf, 4)
local flags = lshift(flags_hi, 8) + flags_lo
-- print(format("flags: 0x%x", flags))
if band(flags, 0x8000) == 0 then
return nil, format("bad QR flag in the DNS response")
end
if band(flags, 0x200) ~= 0 then
return nil, "truncated"
end
local code = band(flags, 0xf)
-- print(format("code: %d", code))
local nqs_hi = byte(buf, 5)
local nqs_lo = byte(buf, 6)
local nqs = lshift(nqs_hi, 8) + nqs_lo
-- print("nqs: ", nqs)
if nqs ~= 1 then
return nil, format("bad number of questions in DNS response: %d", nqs)
end
local nan_hi = byte(buf, 7)
local nan_lo = byte(buf, 8)
local nan = lshift(nan_hi, 8) + nan_lo
-- print("nan: ", nan)
local nns_hi = byte(buf, 9)
local nns_lo = byte(buf, 10)
local nns = lshift(nns_hi, 8) + nns_lo
local nar_hi = byte(buf, 11)
local nar_lo = byte(buf, 12)
local nar = lshift(nar_hi, 8) + nar_lo
-- skip the question part
local ans_qname, pos = _decode_name(buf, 13)
if not ans_qname then
return nil, pos
end
-- print("qname in reply: ", ans_qname)
-- print("question: ", sub(buf, 13, pos))
if pos + 3 + nan * 12 > n then
-- print(format("%d > %d", pos + 3 + nan * 12, n))
return nil, 'truncated';
end
-- question section layout: qname qtype(2) qclass(2)
--[[
local type_hi = byte(buf, pos)
local type_lo = byte(buf, pos + 1)
local ans_type = lshift(type_hi, 8) + type_lo
]]
-- print("ans qtype: ", ans_type)
local class_hi = byte(buf, pos + 2)
local class_lo = byte(buf, pos + 3)
local qclass = lshift(class_hi, 8) + class_lo
-- print("ans qclass: ", qclass)
if qclass ~= 1 then
return nil, format("unknown query class %d in DNS response", qclass)
end
pos = pos + 4
local answers = {}
if code ~= 0 then
answers.errcode = code
answers.errstr = resolver_errstrs[code] or "unknown"
end
local authority_section, additional_section
if opts then
authority_section = opts.authority_section
additional_section = opts.additional_section
if opts.qtype == TYPE_SOA then
authority_section = true
end
end
local err
pos, err = parse_section(answers, SECTION_AN, buf, pos, nan)
if not pos then
return nil, err
end
if not authority_section and not additional_section then
return answers
end
pos, err = parse_section(answers, SECTION_NS, buf, pos, nns,
not authority_section)
if not pos then
return nil, err
end
if not additional_section then
return answers
end
pos, err = parse_section(answers, SECTION_AR, buf, pos, nar)
if not pos then
return nil, err
end
return answers
end
local function _gen_id(self)
local id = self._id -- for regression testing
if id then
return id
end
return rand(0, 65535) -- two bytes
end
local function _tcp_query(self, query, id, opts)
local sock = self.tcp_sock
if not sock then
return nil, "not initialized"
end
log(DEBUG, "query the TCP server due to reply truncation")
local server = _get_cur_server(self)
local ok, err = sock:connect(server[1], server[2])
if not ok then
return nil, "failed to connect to TCP server "
.. concat(server, ":") .. ": " .. err
end
query = concat(query, "")
local len = #query
local len_hi = char(rshift(len, 8))
local len_lo = char(band(len, 0xff))
local bytes, err = sock:send({len_hi, len_lo, query})
if not bytes then
return nil, "failed to send query to TCP server "
.. concat(server, ":") .. ": " .. err
end
local buf, err = sock:receive(2)
if not buf then
return nil, "failed to receive the reply length field from TCP server "
.. concat(server, ":") .. ": " .. err
end
len_hi = byte(buf, 1)
len_lo = byte(buf, 2)
len = lshift(len_hi, 8) + len_lo
-- print("tcp message len: ", len)
buf, err = sock:receive(len)
if not buf then
return nil, "failed to receive the reply message body from TCP server "
.. concat(server, ":") .. ": " .. err
end
local answers, err = parse_response(buf, id, opts)
if not answers then
return nil, "failed to parse the reply from the TCP server "
.. concat(server, ":") .. ": " .. err
end
sock:close()
return answers
end
function _M.tcp_query(self, qname, opts)
local socks = self.socks
if not socks then
return nil, "not initialized"
end
pick_sock(self, socks)
local id = _gen_id(self)
local query, err = _build_request(qname, id, self.no_recurse, opts)
if not query then
return nil, err
end
return _tcp_query(self, query, id, opts)
end
function _M.query(self, qname, opts, tries)
local socks = self.socks
if not socks then
return nil, "not initialized"
end
local id = _gen_id(self)
local query, err = _build_request(qname, id, self.no_recurse, opts)
if not query then
return nil, err
end
-- local cjson = require "cjson"
-- print("query: ", cjson.encode(concat(query, "")))
local retrans = self.retrans
if tries then
tries[1] = nil
end
-- print("retrans: ", retrans)
for i = 1, retrans do
local sock = pick_sock(self, socks)
local ok
ok, err = sock:send(query)
if not ok then
local server = _get_cur_server(self)
err = "failed to send request to UDP server "
.. concat(server, ":") .. ": " .. err
else
local buf
for _ = 1, 128 do
buf, err = sock:receive(4096)
if err then
local server = _get_cur_server(self)
err = "failed to receive reply from UDP server "
.. concat(server, ":") .. ": " .. err
break
end
if buf then
local answers
answers, err = parse_response(buf, id, opts)
if err == "truncated" then
answers, err = _tcp_query(self, query, id, opts)
end
if err and err ~= "id mismatch" then
break
end
if answers then
return answers, nil, tries
end
end
-- only here in case of an "id mismatch"
end
end
if tries then
tries[i] = err
tries[i + 1] = nil -- ensure termination for user supplied table
end
end
return nil, err, tries
end
function _M.compress_ipv6_addr(addr)
local addr = re_sub(addr, "^(0:)+|(:0)+$|:(0:)+", "::", "jo")
if addr == "::0" then
addr = "::"
end
return addr
end
local function _expand_ipv6_addr(addr)
if find(addr, "::", 1, true) then
local ncol, addrlen = 8, #addr
for i = 1, addrlen do
if byte(addr, i) == COLON_CHAR then
ncol = ncol - 1
end
end
if byte(addr, 1) == COLON_CHAR then
addr = "0" .. addr
end
if byte(addr, -1) == COLON_CHAR then
addr = addr .. "0"
end
addr = re_sub(addr, "::", ":" .. rep("0:", ncol), "jo")
end
return addr
end
_M.expand_ipv6_addr = _expand_ipv6_addr
function _M.arpa_str(addr)
if find(addr, ":", 1, true) then
addr = _expand_ipv6_addr(addr)
local idx, hidx, addrlen = 1, 1, #addr
for i = addrlen, 0, -1 do
local s = byte(addr, i)
if s == COLON_CHAR or not s then
for _ = hidx, 4 do
arpa_tmpl[idx] = ZERO_CHAR
idx = idx + 2
end
hidx = 1
else
arpa_tmpl[idx] = s
idx = idx + 2
hidx = hidx + 1
end
end
addr = char(unpack(arpa_tmpl))
else
addr = re_sub(addr, [[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})]],
"$4.$3.$2.$1.in-addr.arpa", "ajo")
end
return addr
end
function _M.reverse_query(self, addr)
return self.query(self, self.arpa_str(addr),
{qtype = self.TYPE_PTR})
end
return _M

View File

@ -0,0 +1,60 @@
local json = require 'json'
local redis = require 'redis'
local response = require 'response'
local module = {
['redis'] = {}
}
module.redis.connect = function()
local red = redis:new();
red:set_timeout(1000);
local ok, err = red:connect('redis', 6379)
if not ok then
ngx.log(ngx.ERR, err)
response.quit(ngx.HTTP_SERVICE_UNAVAILABLE)
return
end
return red
end
module.redis.checkDomain = function(red, category, domain)
local result, err = red:hmget(category, domain)
if err then
ngx.log(ngx.ERR, err)
response.quit(ngx.HTTP_SERVICE_UNAVAILABLE)
return
end
return type(result) == 'string' and true or false
end
local function split(str, pat)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
module.parseURL = function(uri)
local uri = uri or ngx.var.request_uri
return split(uri, '[\\/]+')
end
module.getDomain = function(str)
return string.match(str, '%w+%.%w+$')
end
return module

504
nginx/lua/modules/ip.lua Normal file
View File

@ -0,0 +1,504 @@
--
-- IP address manipulation library in Lua
--
-- @author leite (xico@simbio.se)
-- @license MIT
-- @copyright Simbiose 2015
local math, string, table, bit_available, bit =
require [[math]], require [[string]], require [[table]], pcall(require, 'bit')
-- yey! Lua 5.3 bitwise keywords available
if not bit_available and _VERSION == 'Lua 5.3' then
bit = assert(load([[return {
band = function (a, b) return a & b end,
bor = function (a, b) return a | b end,
rshift = function (a, b) return a >> b end,
lshift = function (a, b) return a << b end
}]]))()
end
local ip, modf, len, match, find, format, concat, insert, band, bor, rshift, lshift, type,
assert, error, tonumber, pcall, setmetatable =
{}, math.modf, string.len, string.match, string.find, string.format, table.concat, table.insert,
bit.band, bit.bor, bit.rshift, bit.lshift, type, assert, error, tonumber, pcall, setmetatable
local _octets, _octet, _part, _parts_with_octets, EMPTY, COLON, ZERO =
'^((0?[xX]?)[%da-fA-F]+)%.((0?[xX]?)[%da-fA-F]+)%.((0?[xX]?)[%da-fA-F]+)%.((0?[xX]?)[%da-fA-F]+)/?(%d*)$',
'^((0?[xX]?)[%da-fA-F]+)((/?)(%d*))$', '(:?)([^:/$]*)(:?)',
'^([:%dxXa-fA-F]-::?)(([%dxXa-fA-F]*)[%.%dxXa-fA-F]*)/?(%d*)$', '', ':', '0'
math, string, bit, table = nil, nil, nil, nil
-- IP special ranges
local special_ranges = {
ipv4 = {
{'unspecified', octets={0, 0, 0, 0}, _cidr=8},
{'broadcast', octets={255, 255, 255, 255}, _cidr=32},
{'multicast', octets={224, 0, 0, 0}, _cidr=4},
{'linkLocal', octets={169, 254, 0, 0}, _cidr=16},
{'loopback', octets={127, 0, 0, 0}, _cidr=8},
{
'private', {octets={10, 0, 0, 0}, _cidr=8}, {octets={172, 16, 0, 0}, _cidr=12},
{octets={192, 168, 0, 0}, _cidr=16}
}, {
'reserved', {octets={192, 0, 0, 0}, _cidr=24}, {octets={192, 0, 2, 0}, _cidr=24},
{octets={192, 88, 99, 0}, _cidr=24}, {octets={198, 51, 100, 0}, _cidr=24},
{octets={203, 0, 113, 0}, _cidr=24}, {octets={240, 0, 0, 0}, _cidr=4}
}
}, ipv6 = {
{'unspecified', parts={0, 0, 0, 0, 0, 0, 0, 0}, _cidr=128},
{'linkLocal', parts={0xfe80, 0, 0, 0, 0, 0, 0, 0}, _cidr=10},
{'multicast', parts={0xff00, 0, 0, 0, 0, 0, 0, 0}, _cidr=8},
{'loopback', parts={0, 0, 0, 0, 0, 0, 0, 1}, _cidr=128},
{'uniqueLocal', parts={0xfc00, 0, 0, 0, 0, 0, 0, 0}, _cidr=7},
{'ipv4Mapped', parts={0, 0, 0, 0, 0, 0xffff, 0, 0}, _cidr=96},
{'rfc6145', parts={0, 0, 0, 0, 0xffff, 0, 0, 0}, _cidr=96},
{'rfc6052', parts={0x64, 0xff9b, 0, 0, 0, 0, 0, 0}, _cidr=96},
{'6to4', parts={0x2002, 0, 0, 0, 0, 0, 0, 0}, _cidr=16},
{'teredo', parts={0x2001, 0, 0, 0, 0, 0, 0, 0}, _cidr=32},
{'reserved', parts={0x2001, 0xdb8, 0, 0, 0, 0, 0, 0}, _cidr=32}
}
}
-- assert ipv4 octets
--
-- @table octets
-- @return boolean, [string]
local function assert_ipv4 (octets)
if not(octets and type(octets) == 'table') then
return false, 'octets should be a table'
end
if not(#octets == 4) then
return false, 'ipv4 octet count should be 4'
end
if not((-1 < octets[1] and 256 > octets[1]) and (-1 < octets[2] and 256 > octets[2]) and
(-1 < octets[3] and 256 > octets[3]) and (-1 < octets[4] and 256 > octets[4])) then
return false, 'ipv4 octet is a byte'
end
return true
end
-- assert ipv6 parts
--
-- @table parts
-- @return boolean, [string]
local function assert_ipv6 (parts)
if not(parts and type(parts) == 'table') then
return false, 'parts should be a table'
end
if not(#parts == 8) then
return false, 'ipv6 part count should be 8'
end
if not((-1 < parts[1] and 0x10000 > parts[1]) and (-1 < parts[2] and 0x10000 > parts[2]) and
(-1 < parts[3] and 0x10000 > parts[3]) and (-1 < parts[4] and 0x10000 > parts[4]) and
(-1 < parts[5] and 0x10000 > parts[5]) and (-1 < parts[6] and 0x10000 > parts[6]) and
(-1 < parts[7] and 0x10000 > parts[7]) and (-1 < parts[8] and 0x10000 > parts[8])) then
return false, 'ipv6 part should fit to two octets'
end
return true
end
-- generic CIDR matcher
--
-- @table first
-- @table second
-- @number part_size
-- @number cidr_bits
-- @return boolean
local function match_cidr(first, second, part_size, cidr_bits)
assert(#first == #second, 'cannot match CIDR for objects with different lengths')
local part, shift = 0, 0
while cidr_bits > 0 do
part = part + 1
shift = part_size - cidr_bits
shift = shift < 0 and 0 or shift
if rshift(first[part], shift) ~= rshift(second[part], shift) then
return false
end
cidr_bits = cidr_bits - part_size
end
return true
end
-- funct address named range matching
--
-- @table address
-- @table range_list
-- @string default_name
-- @return string
local function subnet_match(address, range_list, default_name)
local subnet = {}
for i = 1, #range_list do
subnet = range_list[i]
if #subnet == 1 then
if address:match(subnet) then
return subnet[1]
end
else
for j = 2, #subnet do
if address:match(subnet[j]) then
return subnet[1]
end
end
end
end
return default_name or 'unicast'
end
-- parse IP version 4
--
-- @string string
-- @table octets
-- @number cidr
-- @return boolean, [string]
local function parse_v4(string, octets, cidr)
local value, hex, _, __, _cidr = match(string, _octet)
if value then
value = tonumber(value, hex == ZERO and 8 or nil)
if value > 0xffffffff or value < 0 then
return false, 'address outside defined range'
end
octets[1], octets[2], octets[3], octets[4] =
band(rshift(value, 24), 0xff), band(rshift(value, 16), 0xff),
band(rshift(value, 8), 0xff), band(value, 0xff)
return tonumber(_cidr == EMPTY and 32 or _cidr)
end
local st, _st, nd, _nd, rd, _rd, th, _th, _cidr = match(string, _octets)
if not(st) then
return false, 'invalid ip address'
end
octets[1], octets[2], octets[3], octets[4] =
tonumber(st, _st == ZERO and 8 or nil), tonumber(nd, _nd == ZERO and 8 or nil),
tonumber(rd, _rd == ZERO and 8 or nil), tonumber(th, _th == ZERO and 8 or nil)
return tonumber(_cidr == EMPTY and (cidr and cidr or 32) or _cidr)
end
-- parse IP version 6
--
-- @string string
-- @table parts
-- @table octets
-- @number cidr
-- @return boolean, [string]
local function parse_v6(string, parts, octets, cidr)
local nd_sep, part, l_sep, count, double, length, index, last, string, octets_st, sep, _cidr =
'', '', false, 1, 0, 0, 0, 0, match(string, _parts_with_octets)
if not string or EMPTY == string then
return false, 'invalid ipv6 format'
end
if #octets_st == #sep then
string = string .. sep
else
local err, message = parse_v4(octets_st, octets)
if not err then
return err, message
end
end
_cidr, length, index, last, sep, part, nd_sep =
tonumber(_cidr==EMPTY and (cidr and cidr or 128) or _cidr), len(string), find(string, _part)
while index and index <= length do
if sep == COLON and nd_sep == COLON then
if part == EMPTY or l_sep then
if double > 0 then
return false, 'string is not formatted like ip address'
end
double = count
end
elseif sep == COLON or nd_sep == COLON then
if l_sep and sep == COLON then
if double > 0 then
return false, 'string is not formatted like ip address'
end
double = count
end
end
insert(parts, tonumber(part == EMPTY and '0' or part, 16))
l_sep, count, index, last, sep, part, nd_sep =
nd_sep == COLON, count + 1, find(string, _part, last + 1)
end
if #octets > 0 then
insert(parts, bor(lshift(octets[1], 8), octets[2]))
insert(parts, bor(lshift(octets[3], 8), octets[4]))
length = 7
else
length = 9
end
for index = 1, (length - count) do
insert(parts, double, 0)
end
return _cidr
end
-- ip metatable
local ip_metatable = {
-- set CIDR
--
-- @number cidr
-- @return metatable
cidr = function(self, cidr)
self._cidr = cidr
return self
end,
-- get address named range
--
-- @return string
range = function(self)
return subnet_match(self, special_ranges[self:kind()])
end,
-- get or match address kind
--
-- @string [kind]
-- @return string|boolean
kind = function(self, kind)
local _kind = #self.parts > 0 and 'ipv6' or (#self.octets > 0 and 'ipv4' or EMPTY)
if kind then
return kind == _kind
end
return _kind
end,
-- match two addresses
--
-- @table address
-- @number cidr
-- @return boolean
match = function(self, address, cidr)
if cidr and address._cidr then
address._cidr = cidr
end
return self.__eq(self, address)
end,
-- converts ipv4 to ipv4-mapped ipv6 address
--
-- @return string|nil
ipv4_mapped_address = function (self)
return self:kind('ipv4') and ip.parsev6('::ffff:' .. self:__tostring()) or nil
end,
-- check if it's a ipv4 mapped address
--
-- @return boolean
is_ipv4_mapped = function (self)
return self:range() == 'ipv4Mapped'
end,
-- converts ipv6 ipv4-mapped address to ipv4 address
--
-- @return metatable
ipv4_address = function (self)
assert(self:is_ipv4_mapped(), 'trying to convert a generic ipv6 address to ipv4')
local high, low = self.parts[7], self.parts[8]
return ip.v4({rshift(high, 8), band(high, 0xff), rshift(low, 8), band(low, 0xff)})
end,
-- IP table to string
--
-- @return string
__tostring = function(self)
if self:kind('ipv4') then
return concat(self.octets, '.')
end
local part, state, size, output = '', 0, #self.parts, {}
for i = 1, size do
part = format('%x', self.parts[i])
if 0 == state then
insert(output, (ZERO == part and EMPTY or part))
state = 1
elseif 1 == state then
if ZERO == part then
state = 2
else
insert(output, part)
end
elseif 2 == state then
if ZERO ~= part then
insert(output, EMPTY)
insert(output, part)
state = 3
end
else
insert(output, part)
end
end
if 2 == state then
insert(output, COLON)
end
return concat(output, COLON)
end,
-- compare two IP addresses
--
-- @table value
-- @return boolean
__eq = function(self, value)
if #self.parts > 0 then
assert(value.parts and #value.parts > 0, 'cannot match different address version')
return match_cidr(self.parts, value.parts, 16, value._cidr)
end
assert(value.octets and #value.octets > 0, 'cannot match different address version')
return match_cidr(self.octets, value.octets, 8, value._cidr)
end
}
ip_metatable.__index = ip_metatable
-- create new IP metatable
--
-- @table parts
-- @table octets
-- @number cidr
-- @return metatable
local function new (parts, octets, cidr)
return setmetatable({octets=octets, parts=parts, _cidr=cidr}, ip_metatable)
end
-- assert IP version 4 octets and create it's metatable
--
-- @table octets
-- @number cidr
-- @return metatable
function ip.v4 (octets, cidr)
local err, message = assert_ipv4(octets)
assert(err, message)
return new({}, octets, cidr or 32)
end
-- assert IP version 6 parts and create it's metatable
--
-- @table parts
-- @number cidr
-- @table [octets]
-- @return metatable
function ip.v6 (parts, cidr, octets)
local err, message = assert_ipv6(parts)
assert(err, message)
if octets and #octets > 0 then
err, message = assert_ipv4(octets)
assert(err, message)
end
return new(parts, octets or {}, cidr or 128)
end
-- parse string to IP version 4 metatable
--
-- @string string
-- @number [cidr]
-- @return metatable
function ip.parsev4 (string, cidr)
local octets, message = {}, ''
cidr, message = parse_v4(string, octets, cidr)
assert(cidr ~= false, message)
return ip.v4(octets, cidr)
end
-- parse string to IP version 6 metatable
--
-- @string string
-- @number [cidr]
-- @return metatable
function ip.parsev6 (string, cidr)
local parts, octets, message = {}, {}, ''
cidr, message = parse_v6(string, parts, octets, cidr)
assert(cidr ~= false, message)
return ip.v6(parts, cidr, octets)
end
-- check and parse string to IP metatable
--
-- @string string
-- @return metatable
function ip.parse (string)
if ip.isv6(string) then
return ip.parsev6(string)
elseif ip.isv4(string) then
return ip.parsev4(string)
end
error('the address has neither IPv6 nor IPv4 format')
end
-- check if string is a IP version 4 address
--
-- @string string
-- @boolean validate
-- @return boolean
function ip.isv4 (string, validate)
if validate then
local octets = {}
return parse_v4(string, octets) ~= false and assert_ipv4(octets)
end
return find(string, _octet) ~= nil or find(string, _octets) ~= nil
end
-- check if string is a IP version 6 address
--
-- @string string
-- @boolean validate
-- @return boolean
function ip.isv6 (string, validate)
if validate then
local octets, parts = {}, {}
return parse_v6(string, parts, octets) ~= false and assert_ipv6(parts)
end
return find(string, _parts_with_octets) ~= nil
end
-- check if IP address is valid
--
-- @string string
-- @return boolean
function ip.valid (string)
return pcall(ip.parse, string)
end
return ip

385
nginx/lua/modules/json.lua Normal file
View File

@ -0,0 +1,385 @@
--
-- json.lua
--
-- Copyright (c) 2015 rxi
--
-- This library is free software; you can redistribute it and/or modify it
-- under the terms of the MIT license. See LICENSE for details.
--
local json = { _version = "0.1.0" }
-------------------------------------------------------------------------------
-- Encode
-------------------------------------------------------------------------------
local encode
local escape_char_map = {
[ "\\" ] = "\\\\",
[ "\"" ] = "\\\"",
[ "\b" ] = "\\b",
[ "\f" ] = "\\f",
[ "\n" ] = "\\n",
[ "\r" ] = "\\r",
[ "\t" ] = "\\t",
}
local escape_char_map_inv = { [ "\\/" ] = "/" }
for k, v in pairs(escape_char_map) do
escape_char_map_inv[v] = k
end
local function escape_char(c)
return escape_char_map[c] or string.format("\\u%04x", c:byte())
end
local function encode_nil(val)
return "null"
end
local function encode_table(val, stack)
local res = {}
stack = stack or {}
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if val[1] ~= nil or next(val) == nil then
-- Treat as array -- check keys are valid and it is not sparse
local n = 0
for k in pairs(val) do
if type(k) ~= "number" then
error("invalid table: mixed or invalid key types")
end
n = n + 1
end
if n ~= #val then
error("invalid table: sparse array")
end
-- Encode
for i, v in ipairs(val) do
table.insert(res, encode(v, stack))
end
stack[val] = nil
return "[" .. table.concat(res, ",") .. "]"
else
-- Treat as an object
for k, v in pairs(val) do
if type(k) ~= "string" then
error("invalid table: mixed or invalid key types")
end
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
end
stack[val] = nil
return "{" .. table.concat(res, ",") .. "}"
end
end
local function encode_string(val)
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
end
local function encode_number(val)
-- Check for NaN, -inf and inf
if val ~= val or val <= -math.huge or val >= math.huge then
error("unexpected number value '" .. tostring(val) .. "'")
end
return string.format("%.14g", val)
end
local type_func_map = {
[ "nil" ] = encode_nil,
[ "table" ] = encode_table,
[ "string" ] = encode_string,
[ "number" ] = encode_number,
[ "boolean" ] = tostring,
}
encode = function(val, stack)
local t = type(val)
local f = type_func_map[t]
if f then
return f(val, stack)
end
error("unexpected type '" .. t .. "'")
end
function json.encode(val)
return ( encode(val) )
end
-------------------------------------------------------------------------------
-- Decode
-------------------------------------------------------------------------------
local parse
local function create_set(...)
local res = {}
for i = 1, select("#", ...) do
res[ select(i, ...) ] = true
end
return res
end
local space_chars = create_set(" ", "\t", "\r", "\n")
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
local literals = create_set("true", "false", "null")
local literal_map = {
[ "true" ] = true,
[ "false" ] = false,
[ "null" ] = nil,
}
local function next_char(str, idx, set, negate)
for i = idx, #str do
if set[str:sub(i, i)] ~= negate then
return i
end
end
return #str + 1
end
local function decode_error(str, idx, msg)
local line_count = 1
local col_count = 1
for i = 1, idx - 1 do
col_count = col_count + 1
if str:sub(i, i) == "\n" then
line_count = line_count + 1
col_count = 1
end
end
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
end
local function codepoint_to_utf8(n)
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
local f = math.floor
if n <= 0x7f then
return string.char(n)
elseif n <= 0x7ff then
return string.char(f(n / 64) + 192, n % 64 + 128)
elseif n <= 0xffff then
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
elseif n <= 0x10ffff then
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
f(n % 4096 / 64) + 128, n % 64 + 128)
end
error( string.format("invalid unicode codepoint '%x'", n) )
end
local function parse_unicode_escape(s)
local n1 = tonumber( s:sub(3, 6), 16 )
local n2 = tonumber( s:sub(9, 12), 16 )
-- Surrogate pair?
if n2 then
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
else
return codepoint_to_utf8(n1)
end
end
local function parse_string(str, i)
local has_unicode_escape = false
local has_surrogate_escape = false
local has_escape = false
local last
for j = i + 1, #str do
local x = str:byte(j)
if x < 32 then
decode_error(str, j, "control character in string")
end
if last == 92 then -- "\\" (escape char)
if x == 117 then -- "u" (unicode escape sequence)
local hex = str:sub(j + 1, j + 5)
if not hex:find("%x%x%x%x") then
decode_error(str, j, "invalid unicode escape in string")
end
if hex:find("^[dD][89aAbB]") then
has_surrogate_escape = true
else
has_unicode_escape = true
end
else
local c = string.char(x)
if not escape_chars[c] then
decode_error(str, j, "invalid escape char '" .. c .. "' in string")
end
has_escape = true
end
last = nil
elseif x == 34 then -- '"' (end of string)
local s = str:sub(i + 1, j - 1)
if has_surrogate_escape then
s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape)
end
if has_unicode_escape then
s = s:gsub("\\u....", parse_unicode_escape)
end
if has_escape then
s = s:gsub("\\.", escape_char_map_inv)
end
return s, j + 1
else
last = x
end
end
decode_error(str, i, "expected closing quote for string")
end
local function parse_number(str, i)
local x = next_char(str, i, delim_chars)
local s = str:sub(i, x - 1)
local n = tonumber(s)
if not n then
decode_error(str, i, "invalid number '" .. s .. "'")
end
return n, x
end
local function parse_literal(str, i)
local x = next_char(str, i, delim_chars)
local word = str:sub(i, x - 1)
if not literals[word] then
decode_error(str, i, "invalid literal '" .. word .. "'")
end
return literal_map[word], x
end
local function parse_array(str, i)
local res = {}
local n = 1
i = i + 1
while 1 do
local x
i = next_char(str, i, space_chars, true)
-- Empty / end of array?
if str:sub(i, i) == "]" then
i = i + 1
break
end
-- Read token
x, i = parse(str, i)
res[n] = x
n = n + 1
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "]" then break end
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
end
return res, i
end
local function parse_object(str, i)
local res = {}
i = i + 1
while 1 do
local key, val
i = next_char(str, i, space_chars, true)
-- Empty / end of object?
if str:sub(i, i) == "}" then
i = i + 1
break
end
-- Read key
if str:sub(i, i) ~= '"' then
decode_error(str, i, "expected string for key")
end
key, i = parse(str, i)
-- Read ':' delimiter
i = next_char(str, i, space_chars, true)
if str:sub(i, i) ~= ":" then
decode_error(str, i, "expected ':' after key")
end
i = next_char(str, i + 1, space_chars, true)
-- Read value
val, i = parse(str, i)
-- Set
res[key] = val
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "}" then break end
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
end
return res, i
end
local char_func_map = {
[ '"' ] = parse_string,
[ "0" ] = parse_number,
[ "1" ] = parse_number,
[ "2" ] = parse_number,
[ "3" ] = parse_number,
[ "4" ] = parse_number,
[ "5" ] = parse_number,
[ "6" ] = parse_number,
[ "7" ] = parse_number,
[ "8" ] = parse_number,
[ "9" ] = parse_number,
[ "-" ] = parse_number,
[ "t" ] = parse_literal,
[ "f" ] = parse_literal,
[ "n" ] = parse_literal,
[ "[" ] = parse_array,
[ "{" ] = parse_object,
}
parse = function(str, idx)
local chr = str:sub(idx, idx)
local f = char_func_map[chr]
if f then
return f(str, idx)
end
decode_error(str, idx, "unexpected character '" .. chr .. "'")
end
function json.decode(str)
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
local status, result = pcall(
function()
return parse(str, next_char(str, 1, space_chars, true))
end
)
return result, not status
end
return json

439
nginx/lua/modules/redis.lua Normal file
View File

@ -0,0 +1,439 @@
-- Copyright (C) Yichun Zhang (agentzh)
local sub = string.sub
local byte = string.byte
local tcp = ngx.socket.tcp
local null = ngx.null
local type = type
local pairs = pairs
local unpack = unpack
local setmetatable = setmetatable
local tonumber = tonumber
local tostring = tostring
local rawget = rawget
--local error = error
local ok, new_tab = pcall(require, "table.new")
if not ok or type(new_tab) ~= "function" then
new_tab = function (narr, nrec) return {} end
end
local _M = new_tab(0, 54)
_M._VERSION = '0.26'
local common_cmds = {
"get", "set", "mget", "mset",
"del", "incr", "decr", -- Strings
"llen", "lindex", "lpop", "lpush",
"lrange", "linsert", -- Lists
"hexists", "hget", "hset", "hmget",
--[[ "hmset", ]] "hdel", -- Hashes
"smembers", "sismember", "sadd", "srem",
"sdiff", "sinter", "sunion", -- Sets
"zrange", "zrangebyscore", "zrank", "zadd",
"zrem", "zincrby", -- Sorted Sets
"auth", "eval", "expire", "script",
"sort" -- Others
}
local sub_commands = {
"subscribe", "psubscribe"
}
local unsub_commands = {
"unsubscribe", "punsubscribe"
}
local mt = { __index = _M }
function _M.new(self)
local sock, err = tcp()
if not sock then
return nil, err
end
return setmetatable({ _sock = sock, _subscribed = false }, mt)
end
function _M.set_timeout(self, timeout)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
return sock:settimeout(timeout)
end
function _M.connect(self, ...)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
self._subscribed = false
return sock:connect(...)
end
function _M.set_keepalive(self, ...)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
if rawget(self, "_subscribed") then
return nil, "subscribed state"
end
return sock:setkeepalive(...)
end
function _M.get_reused_times(self)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
return sock:getreusedtimes()
end
local function close(self)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
return sock:close()
end
_M.close = close
local function _read_reply(self, sock)
local line, err = sock:receive()
if not line then
if err == "timeout" and not rawget(self, "_subscribed") then
sock:close()
end
return nil, err
end
local prefix = byte(line)
if prefix == 36 then -- char '$'
-- print("bulk reply")
local size = tonumber(sub(line, 2))
if size < 0 then
return null
end
local data, err = sock:receive(size)
if not data then
if err == "timeout" then
sock:close()
end
return nil, err
end
local dummy, err = sock:receive(2) -- ignore CRLF
if not dummy then
return nil, err
end
return data
elseif prefix == 43 then -- char '+'
-- print("status reply")
return sub(line, 2)
elseif prefix == 42 then -- char '*'
local n = tonumber(sub(line, 2))
-- print("multi-bulk reply: ", n)
if n < 0 then
return null
end
local vals = new_tab(n, 0)
local nvals = 0
for i = 1, n do
local res, err = _read_reply(self, sock)
if res then
nvals = nvals + 1
vals[nvals] = res
elseif res == nil then
return nil, err
else
-- be a valid redis error value
nvals = nvals + 1
vals[nvals] = {false, err}
end
end
return vals
elseif prefix == 58 then -- char ':'
-- print("integer reply")
return tonumber(sub(line, 2))
elseif prefix == 45 then -- char '-'
-- print("error reply: ", n)
return false, sub(line, 2)
else
-- when `line` is an empty string, `prefix` will be equal to nil.
return nil, "unknown prefix: \"" .. tostring(prefix) .. "\""
end
end
local function _gen_req(args)
local nargs = #args
local req = new_tab(nargs * 5 + 1, 0)
req[1] = "*" .. nargs .. "\r\n"
local nbits = 2
for i = 1, nargs do
local arg = args[i]
if type(arg) ~= "string" then
arg = tostring(arg)
end
req[nbits] = "$"
req[nbits + 1] = #arg
req[nbits + 2] = "\r\n"
req[nbits + 3] = arg
req[nbits + 4] = "\r\n"
nbits = nbits + 5
end
-- it is much faster to do string concatenation on the C land
-- in real world (large number of strings in the Lua VM)
return req
end
local function _do_cmd(self, ...)
local args = {...}
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
local req = _gen_req(args)
local reqs = rawget(self, "_reqs")
if reqs then
reqs[#reqs + 1] = req
return
end
-- print("request: ", table.concat(req))
local bytes, err = sock:send(req)
if not bytes then
return nil, err
end
return _read_reply(self, sock)
end
local function _check_subscribed(self, res)
if type(res) == "table"
and (res[1] == "unsubscribe" or res[1] == "punsubscribe")
and res[3] == 0
then
self._subscribed = false
end
end
function _M.read_reply(self)
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
if not rawget(self, "_subscribed") then
return nil, "not subscribed"
end
local res, err = _read_reply(self, sock)
_check_subscribed(self, res)
return res, err
end
for i = 1, #common_cmds do
local cmd = common_cmds[i]
_M[cmd] =
function (self, ...)
return _do_cmd(self, cmd, ...)
end
end
for i = 1, #sub_commands do
local cmd = sub_commands[i]
_M[cmd] =
function (self, ...)
self._subscribed = true
return _do_cmd(self, cmd, ...)
end
end
for i = 1, #unsub_commands do
local cmd = unsub_commands[i]
_M[cmd] =
function (self, ...)
local res, err = _do_cmd(self, cmd, ...)
_check_subscribed(self, res)
return res, err
end
end
function _M.hmset(self, hashname, ...)
if select('#', ...) == 1 then
local t = select(1, ...)
local n = 0
for k, v in pairs(t) do
n = n + 2
end
local array = new_tab(n, 0)
local i = 0
for k, v in pairs(t) do
array[i + 1] = k
array[i + 2] = v
i = i + 2
end
-- print("key", hashname)
return _do_cmd(self, "hmset", hashname, unpack(array))
end
-- backwards compatibility
return _do_cmd(self, "hmset", hashname, ...)
end
function _M.init_pipeline(self, n)
self._reqs = new_tab(n or 4, 0)
end
function _M.cancel_pipeline(self)
self._reqs = nil
end
function _M.commit_pipeline(self)
local reqs = rawget(self, "_reqs")
if not reqs then
return nil, "no pipeline"
end
self._reqs = nil
local sock = rawget(self, "_sock")
if not sock then
return nil, "not initialized"
end
local bytes, err = sock:send(reqs)
if not bytes then
return nil, err
end
local nvals = 0
local nreqs = #reqs
local vals = new_tab(nreqs, 0)
for i = 1, nreqs do
local res, err = _read_reply(self, sock)
if res then
nvals = nvals + 1
vals[nvals] = res
elseif res == nil then
if err == "timeout" then
close(self)
end
return nil, err
else
-- be a valid redis error value
nvals = nvals + 1
vals[nvals] = {false, err}
end
end
return vals
end
function _M.array_to_hash(self, t)
local n = #t
-- print("n = ", n)
local h = new_tab(0, n / 2)
for i = 1, n, 2 do
h[t[i]] = t[i + 1]
end
return h
end
-- this method is deperate since we already do lazy method generation.
function _M.add_commands(...)
local cmds = {...}
for i = 1, #cmds do
local cmd = cmds[i]
_M[cmd] =
function (self, ...)
return _do_cmd(self, cmd, ...)
end
end
end
setmetatable(_M, {__index = function(self, cmd)
local method =
function (self, ...)
return _do_cmd(self, cmd, ...)
end
-- cache the lazily generated method in our
-- module table
_M[cmd] = method
return method
end})
return _M

View File

@ -0,0 +1,22 @@
local json = require 'json'
local module = {}
module.getPostData = function()
local data, err
ngx.req.read_body()
data = ngx.req.get_body_data()
if not data then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
data, err = json.decode(data)
if err or type(data) ~= "table" then
return nil
end
return data
end
return module

View File

@ -0,0 +1,63 @@
local json = require 'json'
local module = {}
module.raw = function(status, data)
ngx.status = status
ngx.say(data)
end
module.json = function(status, data)
ngx.status = status
ngx.header['Content-type'] = 'application/json'
ngx.say(json.encode(data))
end
module.status = function(status)
ngx.status = status
end
module.exit = function(status)
return ngx.exit(status)
end
module.isValidResponseType = function(request_type)
return (request_type == 'raw' or request_type == 'json' or request_type == 'xml' or request_type == 'status') and true or false
end
module.quit = module.exit
module.xml = function(status, data)
local response = '<?xml version="1.0" encoding="utf-8"?><response>'
for i, v in pairs(data) do
response = response .. '<'..i..'>'..tostring(v)..'</'..i..'>'
end
ngx.status = status
response = response .. '</response>'
ngx.header['Content-type'] = 'text/xml; charset=utf-8'
ngx.say(response)
end
module.createResponse = function(response_type, email, domain, isBad)
if response_type == 'status' then
module.status(isBad and ngx.HTTP_FORBIDDEN or ngx.HTTP_OK)
elseif response_type == 'raw' then
module.raw(ngx.HTTP_OK, tostring(isBad))
elseif response_type == 'json' then
module.json(ngx.HTTP_OK, {
['email'] = email,
['domain'] = domain,
['bad'] = isBad
})
elseif response_type == 'xml' then
module.xml(ngx.HTTP_OK, {
['email'] = email,
['domain'] = domain,
['bad'] = isBad
})
end
end
return module

80
nginx/lua/validator.lua Normal file
View File

@ -0,0 +1,80 @@
local request = require 'request'
local response = require 'response'
local helper = require 'helper'
local resolver = require 'dns'
local json = require 'json'
local ip = require 'ip'
local red = helper.redis.connect()
request_uri = helper.parseURL()
if type(request_uri) ~= "table" or table.getn(request_uri) < 2 then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
local response_type = request_uri[2]
if not response.isValidResponseType(response_type) then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
local data = request.getPostData()
if data == nil or data['email'] == nil then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
domain = helper.getDomain(data['email'])
if not domain then
response.quit(ngx.HTTP_BAD_REQUEST)
return
end
local isBad = helper.redis.checkDomain(red, "disposable", domain)
if not isBad or postData['no_dns_check'] == true then
local r, err = resolver:new{
nameservers = {'8.8.8.8', '8.8.4.4'},
retrans = 5,
timeout = 2000,
}
if not r or err then
ngx.log(ngx.ERR, err)
response.quit(ngx.HTTP_SERVICE_UNAVAILABLE)
end
local ans, err = r:tcp_query(domain, { qtype = r.TYPE_MX })
if not ans or err then
ngx.log(ngx.ERR, err)
if type(ans) == "table" then
for i, v in pairs(ans) do
ngx.log(ngx.ERR, json.encode(err))
end
end
response.quit(ngx.HTTP_SERVICE_UNAVAILABLE)
return
end
if not (type(ans) ~= "table" or #ans == 0) then
for _i, _v in pairs(ans) do
local ip_addrs, err = r:tcp_query(_v.exchange)
if not ip_addrs or err or type(ip_addrs) ~= 'table' or #ip_addrs == 0 then
isBad = true
break
end
local p
for i, v in pairs(ip_addrs) do
p = ip.parse(v.address)
if p.range(p) ~= "unicast" then
isBad = true
break
end
end
end
else
isBad = true
end
end
response.createResponse(response_type, data['email'], domain, isBad)

56
node/index.js Normal file
View File

@ -0,0 +1,56 @@
'use strict';
const git = require('simple-git'),
commander = require('commander'),
request = require('request-promise'),
fs = require('fs'),
redis = require("redis");
let pkg = require('./package.json'),
repos = require('./repositories.json'),
client = redis.createClient({
'host': 'redis',
'port': 6379
}),
saveList = [],
domainList = [];
client.on('error', (err) => {
console.error(`[x] ${err.toString()}`);
});
console.log(`[*] Gathering from ${repos.length} sources...`);
Promise.all(repos.map(d => request(d.url))).then((data) => {
repos.forEach((source) => {
console.log(` - ${source.url}`);
});
let tempList = data.join('\n').split('\n');
let domainList = [];
console.log(`[*] Creating domain list...`);
tempList.forEach((domain) => {
if (domain === '') {
return;
}
if (domainList[domain] === undefined) {
domainList[domain] = true;
}
});
domainList = Object.keys(domainList);
console.log(`[*] Found ${domainList.length} domains`);
console.log(`[*] Sorting by alphabet...`);
domainList = domainList.sort((a, b) => a !== b ? a < b ? -1 : 1 : 0);
console.log(`[*] Adding domains to cache...`)
domainList.forEach((domain) => {
client.hset('disposable', domain, true);
});
console.log(`[*] Done!`);
client.quit();
}).catch((err) => {
console.error(err.toString());
console.error(`URL: ${err.options.uri}`);
client.quit();
process.exit(1);
});

468
node/package-lock.json generated Normal file
View File

@ -0,0 +1,468 @@
{
"name": "trash-bot",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ajv": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz",
"integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=",
"requires": {
"co": "4.6.0",
"fast-deep-equal": "1.0.0",
"fast-json-stable-stringify": "2.0.0",
"json-schema-traverse": "0.3.1"
}
},
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA=="
},
"boom": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
"requires": {
"hoek": "4.2.0"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"combined-stream": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
"requires": {
"delayed-stream": "1.0.0"
}
},
"commander": {
"version": "2.12.2",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz",
"integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA=="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cryptiles": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
"requires": {
"boom": "5.2.0"
},
"dependencies": {
"boom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
"requires": {
"hoek": "4.2.0"
}
}
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "1.0.0"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"double-ended-queue": {
"version": "2.1.0-0",
"resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
"integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw="
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"extend": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
"integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
"requires": {
"asynckit": "0.4.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.17"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "1.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
"requires": {
"ajv": "5.5.1",
"har-schema": "2.0.0"
}
},
"hawk": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
"requires": {
"boom": "4.3.1",
"cryptiles": "3.1.2",
"hoek": "4.2.0",
"sntp": "2.1.0"
}
},
"hoek": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
"integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ=="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "1.0.0",
"jsprim": "1.4.1",
"sshpk": "1.13.1"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"mime-db": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
},
"mime-types": {
"version": "2.1.17",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
"requires": {
"mime-db": "1.30.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
},
"qs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
},
"redis": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz",
"integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==",
"requires": {
"double-ended-queue": "2.1.0-0",
"redis-commands": "1.3.1",
"redis-parser": "2.6.0"
}
},
"redis-commands": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz",
"integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs="
},
"redis-parser": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz",
"integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs="
},
"request": {
"version": "2.83.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz",
"integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==",
"requires": {
"aws-sign2": "0.7.0",
"aws4": "1.6.0",
"caseless": "0.12.0",
"combined-stream": "1.0.5",
"extend": "3.0.1",
"forever-agent": "0.6.1",
"form-data": "2.3.1",
"har-validator": "5.0.3",
"hawk": "6.0.2",
"http-signature": "1.2.0",
"is-typedarray": "1.0.0",
"isstream": "0.1.2",
"json-stringify-safe": "5.0.1",
"mime-types": "2.1.17",
"oauth-sign": "0.8.2",
"performance-now": "2.1.0",
"qs": "6.5.1",
"safe-buffer": "5.1.1",
"stringstream": "0.0.5",
"tough-cookie": "2.3.3",
"tunnel-agent": "0.6.0",
"uuid": "3.1.0"
}
},
"request-promise": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
"integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
"requires": {
"bluebird": "3.5.1",
"request-promise-core": "1.1.1",
"stealthy-require": "1.1.1",
"tough-cookie": "2.3.3"
}
},
"request-promise-core": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
"integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
"requires": {
"lodash": "4.17.4"
},
"dependencies": {
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
}
}
},
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"simple-git": {
"version": "1.83.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.83.0.tgz",
"integrity": "sha1-OiaE32L3W6TnleE2QtArnYV/wJ0=",
"requires": {
"debug": "3.1.0"
}
},
"sntp": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
"requires": {
"hoek": "4.2.0"
}
},
"sshpk": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.1",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
}
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"stringstream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
},
"tough-cookie": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
"integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
"requires": {
"punycode": "1.4.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "5.1.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
},
"uuid": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "1.3.0"
}
}
}
}

19
node/package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "trash-bot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "./index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"commander": "^2.12.2",
"redis": "^2.8.0",
"request": "^2.83.0",
"request-promise": "^4.2.2",
"simple-git": "^1.83.0"
}
}

6
node/repositories.json Normal file
View File

@ -0,0 +1,6 @@
[
{
"name": "adamloving temporary email address domains",
"url": "https://gist.githubusercontent.com/adamloving/4401361/raw/db901ef28d20af8aa91bf5082f5197d27926dea4/temporary-email-address-domains"
}
]