mirror of
https://github.com/aculix/ticket-monitoring.git
synced 2026-10-27 07:15:51 +00:00
fix: make the SOCKS5 proxy work for BookMyShow too
BookMyShow blocks datacenter IPs on top of TLS fingerprinting, confirmed by CI runners getting 403 with a working impersonation, so cloud hosts need the proxy for BMS as well as District. impit resolves DNS locally for socks5:// and hands an IPv6-only exit an unreachable IPv4 address, so the scheme is normalized to socks5h://. Verified end to end: a proxied BMS check returns 200 and alerts. Docs said the proxy did nothing for BookMyShow, which was wrong.
This commit is contained in:
1 parent
608221fe18
commit
5f86252df1
4 files changed
+28
-13
No files matched your search
+4
-3
@@ -60,7 +60,8 @@ CURRENCY=₹
|
|||||||
STATE_PATH=./state.json # Docker image defaults this to /data/state.json
|
STATE_PATH=./state.json # Docker image defaults this to /data/state.json
|
||||||
PORT=4733 # status endpoint (--loop mode only)
|
PORT=4733 # status endpoint (--loop mode only)
|
||||||
|
|
||||||
# Routes District checks through a SOCKS5 proxy; notifications stay direct.
|
# Routes both sites' checks through a SOCKS5 proxy; notifications stay direct.
|
||||||
# Needed on datacenter hosts, whose IPs District's WAF blocks. It does nothing for
|
# Both District and BookMyShow block datacenter IPs, so a cloud host usually needs this.
|
||||||
# BookMyShow, which blocks on TLS fingerprint rather than IP (impit handles that).
|
# socks5:// is rewritten to socks5h:// internally, so the proxy resolves DNS. That is
|
||||||
|
# required for IPv6-only exits and harmless otherwise.
|
||||||
# PROXY_URL=socks5://user:pass@proxy.example.net:1080
|
# PROXY_URL=socks5://user:pass@proxy.example.net:1080
|
||||||
@@ -181,7 +181,7 @@ with comments in [`.env.example`](.env.example).
|
|||||||
| `EXPIRY_UTC` | *auto* | When to retire. Defaults to local midnight after `TARGET_DATE`. |
|
| `EXPIRY_UTC` | *auto* | When to retire. Defaults to local midnight after `TARGET_DATE`. |
|
||||||
| `STATE_PATH` | `./state.json` | Where dedupe state lives, `/data/state.json` in Docker |
|
| `STATE_PATH` | `./state.json` | Where dedupe state lives, `/data/state.json` in Docker |
|
||||||
| `PORT` | `4733` | Status endpoint |
|
| `PORT` | `4733` | Status endpoint |
|
||||||
| `PROXY_URL` | | SOCKS5 proxy for District checks, see below |
|
| `PROXY_URL` | | SOCKS5 proxy for both sites' checks, see below |
|
||||||
|
|
||||||
v1 used flat names (`MOVIE_CODE`, `CINEMA_ID` and friends) for District. Those still work, so an
|
v1 used flat names (`MOVIE_CODE`, `CINEMA_ID` and friends) for District. Those still work, so an
|
||||||
existing `.env` keeps running unchanged.
|
existing `.env` keeps running unchanged.
|
||||||
@@ -210,13 +210,21 @@ permanently, while a home connection was never touched once. Either run it from
|
|||||||
connection, or point `PROXY_URL` at a SOCKS5 proxy. Only the site checks go through the proxy.
|
connection, or point `PROXY_URL` at a SOCKS5 proxy. Only the site checks go through the proxy.
|
||||||
Notifications stay direct, so your alerts don't depend on it.
|
Notifications stay direct, so your alerts don't depend on it.
|
||||||
|
|
||||||
|
One gotcha if your proxy is IPv6-only: a `socks5://` URL makes some clients resolve DNS locally
|
||||||
|
and hand the proxy an IPv4 address it cannot reach. The monitor rewrites the scheme to `socks5h://`
|
||||||
|
so the proxy does the resolving, which fixes that and changes nothing for other proxies.
|
||||||
|
|
||||||
### BookMyShow returns HTTP 403
|
### BookMyShow returns HTTP 403
|
||||||
|
|
||||||
BookMyShow blocks on the TLS fingerprint of the client, not on your IP, which is why plain
|
BookMyShow blocks on two things at once. First the TLS fingerprint of the client, which is why
|
||||||
`curl` and Node's `fetch` both get 403 no matter which headers or cookies you send. A proxy
|
plain `curl` and Node's `fetch` get 403 no matter which headers or cookies you send. That part is
|
||||||
won't help either. This is handled with [impit](https://github.com/apify/impit), which performs
|
handled by [impit](https://github.com/apify/impit), which performs the request with a real Chrome
|
||||||
the request with a real Chrome fingerprint. If you see 403s here, the impersonation has probably
|
fingerprint. Second your IP, if it belongs to a datacenter: BookMyShow 403s cloud hosts even with
|
||||||
stopped matching, so try updating the image or `npm update impit`.
|
a perfect fingerprint, which I confirmed from GitHub Actions runners.
|
||||||
|
|
||||||
|
So on a cloud host you need both, and setting `PROXY_URL` covers the second half. If you are still
|
||||||
|
getting 403s from a residential connection, the impersonation has probably stopped matching the
|
||||||
|
current Chrome, so update the image or run `npm update impit`.
|
||||||
|
|
||||||
### ntfy returns HTTP 429
|
### ntfy returns HTTP 429
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -33,9 +33,11 @@ function writeState(cfg, state) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Routes provider requests through a SOCKS5 proxy. Notifications stay direct, so the
|
* Routes provider requests through a SOCKS5 proxy. Notifications stay direct, so the
|
||||||
* alerting path never depends on the proxy. District needs this on datacenter hosts whose
|
* alerting path never depends on the proxy.
|
||||||
* IP the WAF blocks. It does nothing for BookMyShow, which blocks on TLS fingerprint
|
*
|
||||||
* rather than IP; impit handles that instead.
|
* Both sites block datacenter IPs, so a cloud host generally needs this for both. It is
|
||||||
|
* only half the story for BookMyShow, which also blocks on TLS fingerprint: impit deals
|
||||||
|
* with the fingerprint, the proxy deals with the IP, and BMS needs both.
|
||||||
*/
|
*/
|
||||||
async function attachProxy(cfg) {
|
async function attachProxy(cfg) {
|
||||||
if (!cfg.proxyUrl) return;
|
if (!cfg.proxyUrl) return;
|
||||||
|
|||||||
@@ -18,9 +18,13 @@ let client = null;
|
|||||||
async function getClient(cfg) {
|
async function getClient(cfg) {
|
||||||
if (client) return client;
|
if (client) return client;
|
||||||
if (!Impit) ({ Impit } = await import("impit"));
|
if (!Impit) ({ Impit } = await import("impit"));
|
||||||
|
// With socks5:// impit resolves DNS locally and asks the proxy for that address,
|
||||||
|
// which fails outright on an IPv6-only exit that cannot reach the IPv4 we picked.
|
||||||
|
// socks5h:// leaves resolution to the proxy, so normalize to it.
|
||||||
|
const proxyUrl = cfg.proxyUrl ? cfg.proxyUrl.replace(/^socks5:\/\//i, "socks5h://") : "";
|
||||||
client = new Impit({
|
client = new Impit({
|
||||||
browser: "chrome",
|
browser: "chrome",
|
||||||
...(cfg.proxyUrl ? { proxyUrl: cfg.proxyUrl } : {}),
|
...(proxyUrl ? { proxyUrl } : {}),
|
||||||
});
|
});
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user