-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathindex.js
140 lines (116 loc) · 3.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
const ProxyLists = require('proxy-lists');
const ip = require('ip');
const { promisify } = require('util');
const writeFile = promisify(require('fs').writeFile);
const readFile = promisify(require('fs').readFile);
const exec = promisify(require('child_process').exec);
const PROXY_OPTIONS = {
countries: ['us'],
sourcesBlackList: ['kingproxies', 'bitproxies']
};
const CWD = process.cwd()
const PORT = process.env.PORT || 1339
const REFRESH_RATE = process.env.REFRESH_RATE || 60
const PID_FILE = `${CWD}/ha.pid`;
const CFG_FILE = `${CWD}/haproxy.cfg`;
const HAPROXY_CMD = 'haproxy';
function renderProxies(proxies) {
return proxies
.filter(proxy => proxy !== undefined)
.map((proxy, i) => ` server proxy${i} ${proxy.trim()}`) // intentional 2 spaces
.join('\n');
}
function getConfig(proxies) {
return `
global
maxconn 1024
pidfile ha.pid
daemon
defaults
mode http
maxconn 1024
option httplog
option dontlognull
retries 1
timeout connect 5s
timeout client 20s
timeout server 20s
frontend localnodes
bind *:${PORT}
mode http
default_backend proxies
backend proxies
balance roundrobin
option http_proxy
${renderProxies(proxies)}
`;
}
function getProxyList() {
let proxyList = {};
return new Promise((resolve, reject) => {
ProxyLists.getProxies(PROXY_OPTIONS)
.on('data', proxies => {
proxies.forEach(proxy => {
if (!ip.isV4Format(proxy.ipAddress)) return;
if (proxy.port < 80) return;
if (proxy.port === PORT) return;
const el = `${proxy.ipAddress}:${proxy.port}`;
proxyList[el] = 0; // if i figure out a good way to ping in node, ping server here
});
})
.on('end', () => {resolve(proxyList)})
.on('error', err => {
console.log(err)
reject(err)
});
});
}
function sortProxiesByPing(proxies) {
return Object.keys(proxies).sort((a, b) => proxies[a] - proxies[b]);
}
function getHaproxyPID() {
return readFile(`${PID_FILE}`);
}
function startHaproxy() {
console.log('launching haproxy');
return exec(`${HAPROXY_CMD} -f ${CFG_FILE}`);
}
function reloadHaproxy() {
console.log('reloading haproxy');
return exec(`${HAPROXY_CMD} -sf $(cat ${PID_FILE}) -f ${CFG_FILE}`);
}
function killHaproxy() {
console.log('killing existing haproxy');
return exec(`kill -9 $(cat ${PID_FILE}) 2>/dev/null`);
}
function saveHaproxyConfig(config) {
return writeFile(`${CFG_FILE}`, config);
}
async function getAndSaveProxyList() {
console.log('fetching proxies');
const proxyList = await getProxyList();
const keys = Object.keys(proxyList);
const config = getConfig(keys.slice(0, 4095)); // haproxy max servers
await saveHaproxyConfig(config);
}
function tick() {
setTimeout(async () => {
try {
await getAndSaveProxyList();
await reloadHaproxy();
} catch (e) {
console.warn(e);
}
return tick();
}, REFRESH_RATE * 1000);
}
async function main() {
try {
await getAndSaveProxyList();
await startHaproxy();
} catch (e) {
console.warn(e);
}
tick();
}
main();