{"id":13603028,"url":"https://github.com/EtherDream/web-frontend-magic","last_synced_at":"2025-04-11T13:32:28.151Z","repository":{"id":39404602,"uuid":"221634151","full_name":"EtherDream/web-frontend-magic","owner":"EtherDream","description":"#前端黑魔法# 整理","archived":false,"fork":false,"pushed_at":"2021-10-16T11:49:30.000Z","size":411,"stargazers_count":785,"open_issues_count":7,"forks_count":33,"subscribers_count":27,"default_branch":"master","last_synced_at":"2024-08-02T18:43:40.575Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EtherDream.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-14T07:09:23.000Z","updated_at":"2024-07-24T09:34:33.000Z","dependencies_parsed_at":"2022-08-01T08:19:41.517Z","dependency_job_id":null,"html_url":"https://github.com/EtherDream/web-frontend-magic","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Fweb-frontend-magic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Fweb-frontend-magic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Fweb-frontend-magic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EtherDream%2Fweb-frontend-magic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EtherDream","download_url":"https://codeload.github.com/EtherDream/web-frontend-magic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223470406,"owners_count":17150547,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T18:01:47.049Z","updated_at":"2024-11-07T06:30:59.347Z","avatar_url":"https://github.com/EtherDream.png","language":null,"funding_links":[],"categories":["Others"],"sub_categories":[],"readme":"# Web 前端黑魔法\n\n![](logo.png)\n\n收集整理过去发表的 #前端黑魔法# 话题。\n\n在此怀念和 [@zswang](https://github.com/zswang) 交流探讨前端黑魔法的时光。\n\n\n# 2019\n\n## HTTP 缓存更新\n\n使用 fetch API 可更新 HTTP 缓存数据：\n\n```js\nfetch(url, {\n  cache: 'no-cache',\n})\n```\n\n设置 `cache` 选项为 `no-cache` 时，浏览器无视本地 HTTP 缓存，强制发起请求，并将最新内容覆盖已有缓存。\n\n详细查看：https://www.cnblogs.com/index-html/p/http-cache-hotfix.html\n\n\n## 检测浏览器代理\n\n由于大部分 socks5 代理只转发数据，不转发 TCP 头，因此后端返回数据时附带一个特殊的 TCP 头，然后前端验证该头是否生效，即可推断否是存在代理。\n\n例如后端下发 tcpwin=0 的控制信息，正常情况下前端收到后不会再往外发包，数据累计在协议栈缓冲区里。该特征可通过 WebSocket.bufferAmount 属性检测；而有代理的情况下，数据被累积在了代理服务的缓冲区，前端仍能往代理服务发包，缓冲区不会有累积。\n\n演示：https://www.etherdream.com/proxy-detect/tcpwin.html\n\n后端实现也很简单，NodeJS 实现 ws 服务，通过 setsockopt 给 socket 设置 mark，结合 tc 改包。\n\n\u003cdetails\u003e\n\u003csummary\u003eSHOW ME THE CODE\u003c/summary\u003e\n\n```js\n// test.js\nconst {setsockopt} = require('sockopt')\nconst {WebSocketServer} = require('ws')\nconst wss = new WebSocketServer({port: 8080})\n\nwss.on('connection', (ws, req) =\u003e {\n  console.log(req.socket.remoteAddress + ':' + req.socket.remotePort)\n  setsockopt(req.socket, 1 /* SOL_SOCKET */, 36 /* SO_MARK */, 1 /* mark */)\n  ws.send('')\n  setTimeout(() =\u003e ws.terminate(), 2000)\n})\n```\n\n```bash\n# reset tc rules\ntc qdisc del dev eth0 root\ntc qdisc replace dev eth0 root handle 1: htb\n\n# if mark = 1 then tcp.win = 0\ntc filter add dev eth0 parent 1: u32 \\\n  match mark 1 0xffffffff \\\n  action pedit munge offset 34 u16 set 0 pipe \\\n  csum ip and tcp\n\nnpm install ws sockopt\nnode test.js\n```\n\nHTTPS 同样支持。但不能运行在 CloudFlare 之类的服务后面，否则 TCP 特殊头就丢失了。如果网络会自动重算 checksum，那么 `pipe csum ip and tcp` 可省略。\n\u003c/details\u003e\n\n\n## 发送 UDP 无状态包\n\nWebRTC 可发送 UDP 数据，但必须先经过握手等环节。有没有办法，第一个包就能携带自定义数据？\n\nWebRTC 传统用法是 P2P 通信，双方先通过 STUN 服务查询自己的公网地址并完成打洞，然后交换 SDP 等信息，相互连接。\n\n但如果是 C/S 通信，服务端地址已知，那么客户端可跳过打洞步骤，直接虚构一份 SDP，把对方地址填进去就可以发包了。SDP 中的 `ice-ufrag` 会明文出现在 UDP 包中。该参数接受字母、数字和 #+-/=_ 共 68 种字符，最大长度 256，因此可携带一定量的信息到服务端。\n\n----\n\n一个比较有意义的应用场景是端口敲门：目标服务器（任意服务都可以）默认禁止所有 IP，通过传送门页面给它发 UDP 敲门包。服务器收到预期的 UDP 后，将该包的源 IP 加入白名单。 \n\n演示：https://www.etherdream.com/port-knocking/\n\n点击按钮之前无法访问目标服务，点击按钮之后就可以访问了。使用这个方案，即可抵挡后台管理服务的暴力破解，以及其他的扫描流量。也可以用于 DDOS/CC 防御（比如用 GitHub Pages 这种打不垮的页面做传送门）\n\n![image](https://user-images.githubusercontent.com/1072787/130002091-ff85caad-7866-423c-b41e-a84861553e52.png)\n\n![image](https://user-images.githubusercontent.com/1072787/130002182-f14dfb40-400d-4e1f-ac4d-13d10a1c1432.png)\n\n更多参考：https://www.cnblogs.com/index-html/p/js-port-knocking.html\n\n\n## 获取往返数据包的 TTL\n\n后端获取用户的 TTL 很容易，但在浏览器上获取后端的 TTL 很麻烦。\n\n不过有个黑科技，可以让后端返回的包反弹回服务器 —— 只要前端在收到数据前释放 socket，之后操作系统找不到目标端口，就会发送「ICMP 端口不可到达」给服务器，其中封装了返回包的头部信息。\n\n演示：https://www.etherdream.com/test/stunex.html\n\n详细参考：https://www.cnblogs.com/index-html/p/js-get-round-trip-ttl.html\n\n\n# 更早的\n\n下面大多从 weibo 搬运过来，账号 @EtherDream 去年被禁言，以后在此更新。表情符已替换成 ~（大部分可脑补成狗头）\n\n[2018.md](https://github.com/EtherDream/web-frontend-magic/blob/master/2018.md)\n\n[2017.md](https://github.com/EtherDream/web-frontend-magic/blob/master/2017.md)\n\n[2016.md](https://github.com/EtherDream/web-frontend-magic/blob/master/2016.md)\n\n[2015.md](https://github.com/EtherDream/web-frontend-magic/blob/master/2015.md)\n\n[2014.md](https://github.com/EtherDream/web-frontend-magic/blob/master/2014.md)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEtherDream%2Fweb-frontend-magic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEtherDream%2Fweb-frontend-magic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEtherDream%2Fweb-frontend-magic/lists"}