{"id":6411,"date":"2024-08-29T12:01:57","date_gmt":"2024-08-29T04:01:57","guid":{"rendered":"http:\/\/wordpress.jiyun.net\/?p=6411"},"modified":"2024-11-30T20:18:41","modified_gmt":"2024-11-30T12:18:41","slug":"cf-workers-vless%e6%b0%b8%e4%b9%85%e5%85%8d%e8%b4%b9%e8%8a%82%e7%82%b9%e6%90%ad%e5%bb%ba","status":"publish","type":"post","link":"http:\/\/puo.cn\/?p=6411","title":{"rendered":"CF workers vless\u6c38\u4e45\u514d\u8d39\u8282\u70b9\u642d\u5efa"},"content":{"rendered":"<article id=\"article-container\" class=\"post-content\">\n<h2 id=\"\u90e8\u7f72\">\u90e8\u7f72<\/h2>\n<p>\u8fdb\u5165cloudflare\u521b\u5efaworkers<\/p>\n<p>\u7136\u540e\u8fdb\u5165\u4f60\u7684\u4ee3\u7801\u7f16\u8f91\u9875\u9762\uff0c\u7c98\u8d34\u4e0b\u65b9\u4ee3\u7801\u3002<\/p>\n<p>\u9700\u8981\u6539\u52a8\u4ee5\u4e0b\u5185\u5bb9<\/p>\n<h4 id=\"userID\"><code>userID<\/code><\/h4>\n<p>\u6b64\u4e3avless\u9274\u5b9a\u7528\u6237\u7684id\uff0c\u9700\u81ea\u884c\u751f\u6210\u5e76\u66ff\u6362\u3002<\/p>\n<h3 id=\"proxyIPs\"><code>proxyIPs<\/code><\/h3>\n<p>\u4ee3\u7406\u670d\u52a1\u5668\u7684\u57df\u540d\u6216IP\u5730\u5740,\u5373\u5229\u7528\u54ea\u4e9b\u53ef\u4ee5\u7684cloud flare\u53cd\u4ee3\u3002<\/p>\n<figure class=\"highlight js\">\n<div class=\"highlight-tools \"><i class=\"fas fa-angle-down expand \"><\/i><\/p>\n<div class=\"code-lang\">JS<\/div>\n<div class=\"copy-notice\"><\/div>\n<p><i class=\"fas fa-paste copy-button\"><\/i><\/div>\n<table>\n<tbody>\n<tr>\n<td class=\"gutter\">\n<pre><span class=\"line\">1<\/span>\n<span class=\"line\">2<\/span>\n<span class=\"line\">3<\/span>\n<span class=\"line\">4<\/span>\n<span class=\"line\">5<\/span>\n<span class=\"line\">6<\/span><\/pre>\n<\/td>\n<td class=\"code\">\n<pre><span class=\"line\"><span class=\"keyword\">const<\/span> proxyIPs = [<\/span>\n<span class=\"line\">    <span class=\"string\">\"workers.cloudflare.cyou\"<\/span>,<\/span>\n<span class=\"line\">    <span class=\"string\">\"cdn.xn--b6gac.eu.org\"<\/span>,<\/span>\n<span class=\"line\">    <span class=\"string\">\"cdn-all.xn--b6gac.eu.org\"<\/span>,<\/span>\n<span class=\"line\">    <span class=\"string\">\"edgetunnel.anycast.eu.org\"<\/span><\/span>\n<span class=\"line\">];<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h3 id=\"cn-hostnames\"><code>cn_hostnames<\/code><\/h3>\n<p>\u5728\u4ee3\u7801\u6700\u540e\u90e8\u5206\uff0c\u8868\u793a\u4f2a\u88c5\u57df\u540d<\/p>\n<h2 id=\"\u67e5\u770b\u90e8\u7f72\u60c5\u51b5\">\u67e5\u770b\u90e8\u7f72\u60c5\u51b5<\/h2>\n<p>\u5982\u56fe\uff0c<code>Subdomain<\/code>\u662f\u4f60\u7684\u5b50\u57df\uff0c\u5982\u679c\u4f60\u7684workers\u4e3avless\uff0c\u90a3\u4e48\u5bf9\u5e94\u5730\u5740\u5373\u4e3avless.username.workers.dev<\/p>\n<p>\u8bbf\u95ee\u8be5\u5730\u5740\u5373\u663e\u793a\u4f2a\u88c5\u57df\u540d\uff08<code>cn_hostnames<\/code>\uff09\u5bf9\u5e94\u9875\u9762<\/p>\n<p>\u5728\u4f2a\u88c5\u57df\u540d\u540e\u6dfb\u52a0\u4e4b\u524d\u8f93\u5165\u7684userid\u5373\u53ef\u770b\u5230\u4ee3\u7406\u4fe1\u606f\u3002<\/p>\n<h3 id=\"\u81ea\u5b9a\u4e49\u57df\u540d\u5f00\u542fTLS\">\u81ea\u5b9a\u4e49\u57df\u540d\u5f00\u542fTLS<\/h3>\n<p>\u5f00\u542fTLS\u9700\u8981\u81ea\u5b9a\u4e49\u57df\u540d\uff0c\u5f00\u542fTLS\u5b89\u5168\u6027\u4f1a\u663e\u8457\u9ad8\u4e8e\u4e3a\u5f00\u542f\uff0c\u90e8\u7f72workers\u5f00\u542fTLS\u9700\u8981\u81ea\u5b9a\u4e49\u57df\u540d\u3002<\/p>\n<p>\u627e\u5230\u521a\u521a\u90e8\u7f72\u7684vless\uff0c\u4e3a\u5176\u6dfb\u52a0\u5df2\u7ecf\u5728cloudflare\u89e3\u6790\u7684\u57df\u540d\uff08\u6216\u5b50\u57df\uff09<\/p>\n<p>\u8bbe\u7f6e\u5b8c\u6210\u540e\uff0c\u5728\u6d4f\u89c8\u5668\u5730\u5740\u680f\u8f93\u5165\uff1a\u4f60\u8bbe\u7f6e\u7684\u81ea\u5b9a\u4e49\u57df\u540d\/\u4f60\u8bbe\u7f6e\u7684UUID\uff0c\u53ea\u8981\u8fd9\u6837\u624d\u4f1a\u663e\u793a\u51fatls\u914d\u7f6e<\/p>\n<h3 id=\"\u81ea\u9009\u57df\u540d\">\u81ea\u9009\u57df\u540d<\/h3>\n<p><a rel=\"nofollow\" href=\"http:\/\/icook.tw\/\" target=\"_blank\" rel=\"noopener external nofollow noreferrer\">icook.tw<\/a><\/p>\n<p>\u5373\u6cdb\u64adcloudflare\uff0c\u89e3\u6790\u57df\u540d\u5373\u53ef\u5f97\u5230\u8f83\u5feb\u7684ip<\/p>\n<h2 id=\"\u4ee3\u7801\u5982\u4e0b\">\u4ee3\u7801\u5982\u4e0b<\/h2>\n<figure class=\"highlight js\">\n<div class=\"highlight-tools \"><i class=\"fas fa-angle-down expand \"><\/i><\/p>\n<div class=\"code-lang\">JS<\/div>\n<div class=\"copy-notice\"><\/div>\n<p><i class=\"fas fa-paste copy-button\"><\/i><\/div>\n<table>\n<tbody>\n<tr>\n<td class=\"gutter\">\n<pre><span class=\"line\">1<\/span>\n<span class=\"line\">2<\/span>\n<span class=\"line\">3<\/span>\n<span class=\"line\">4<\/span>\n<span class=\"line\">5<\/span>\n<span class=\"line\">6<\/span>\n<span class=\"line\">7<\/span>\n<span class=\"line\">8<\/span>\n<span class=\"line\">9<\/span>\n<span class=\"line\">10<\/span>\n<span class=\"line\">11<\/span>\n<span class=\"line\">12<\/span>\n<span class=\"line\">13<\/span>\n<span class=\"line\">14<\/span>\n<span class=\"line\">15<\/span>\n<span class=\"line\">16<\/span>\n<span class=\"line\">17<\/span>\n<span class=\"line\">18<\/span>\n<span class=\"line\">19<\/span>\n<span class=\"line\">20<\/span>\n<span class=\"line\">21<\/span>\n<span class=\"line\">22<\/span>\n<span class=\"line\">23<\/span>\n<span class=\"line\">24<\/span>\n<span class=\"line\">25<\/span>\n<span class=\"line\">26<\/span>\n<span class=\"line\">27<\/span>\n<span class=\"line\">28<\/span>\n<span class=\"line\">29<\/span>\n<span class=\"line\">30<\/span>\n<span class=\"line\">31<\/span>\n<span class=\"line\">32<\/span>\n<span class=\"line\">33<\/span>\n<span class=\"line\">34<\/span>\n<span class=\"line\">35<\/span>\n<span class=\"line\">36<\/span>\n<span class=\"line\">37<\/span>\n<span class=\"line\">38<\/span>\n<span class=\"line\">39<\/span>\n<span class=\"line\">40<\/span>\n<span class=\"line\">41<\/span>\n<span class=\"line\">42<\/span>\n<span class=\"line\">43<\/span>\n<span class=\"line\">44<\/span>\n<span class=\"line\">45<\/span>\n<span class=\"line\">46<\/span>\n<span class=\"line\">47<\/span>\n<span class=\"line\">48<\/span>\n<span class=\"line\">49<\/span>\n<span class=\"line\">50<\/span>\n<span class=\"line\">51<\/span>\n<span class=\"line\">52<\/span>\n<span class=\"line\">53<\/span>\n<span class=\"line\">54<\/span>\n<span class=\"line\">55<\/span>\n<span class=\"line\">56<\/span>\n<span class=\"line\">57<\/span>\n<span class=\"line\">58<\/span>\n<span class=\"line\">59<\/span>\n<span class=\"line\">60<\/span>\n<span class=\"line\">61<\/span>\n<span class=\"line\">62<\/span>\n<span class=\"line\">63<\/span>\n<span class=\"line\">64<\/span>\n<span class=\"line\">65<\/span>\n<span class=\"line\">66<\/span>\n<span class=\"line\">67<\/span>\n<span class=\"line\">68<\/span>\n<span class=\"line\">69<\/span>\n<span class=\"line\">70<\/span>\n<span class=\"line\">71<\/span>\n<span class=\"line\">72<\/span>\n<span class=\"line\">73<\/span>\n<span class=\"line\">74<\/span>\n<span class=\"line\">75<\/span>\n<span class=\"line\">76<\/span>\n<span class=\"line\">77<\/span>\n<span class=\"line\">78<\/span>\n<span class=\"line\">79<\/span>\n<span class=\"line\">80<\/span>\n<span class=\"line\">81<\/span>\n<span class=\"line\">82<\/span>\n<span class=\"line\">83<\/span>\n<span class=\"line\">84<\/span>\n<span class=\"line\">85<\/span>\n<span class=\"line\">86<\/span>\n<span class=\"line\">87<\/span>\n<span class=\"line\">88<\/span>\n<span class=\"line\">89<\/span>\n<span class=\"line\">90<\/span>\n<span class=\"line\">91<\/span>\n<span class=\"line\">92<\/span>\n<span class=\"line\">93<\/span>\n<span class=\"line\">94<\/span>\n<span class=\"line\">95<\/span>\n<span class=\"line\">96<\/span>\n<span class=\"line\">97<\/span>\n<span class=\"line\">98<\/span>\n<span class=\"line\">99<\/span>\n<span class=\"line\">100<\/span>\n<span class=\"line\">101<\/span>\n<span class=\"line\">102<\/span>\n<span class=\"line\">103<\/span>\n<span class=\"line\">104<\/span>\n<span class=\"line\">105<\/span>\n<span class=\"line\">106<\/span>\n<span class=\"line\">107<\/span>\n<span class=\"line\">108<\/span>\n<span class=\"line\">109<\/span>\n<span class=\"line\">110<\/span>\n<span class=\"line\">111<\/span>\n<span class=\"line\">112<\/span>\n<span class=\"line\">113<\/span>\n<span class=\"line\">114<\/span>\n<span class=\"line\">115<\/span>\n<span class=\"line\">116<\/span>\n<span class=\"line\">117<\/span>\n<span class=\"line\">118<\/span>\n<span class=\"line\">119<\/span>\n<span class=\"line\">120<\/span>\n<span class=\"line\">121<\/span>\n<span class=\"line\">122<\/span>\n<span class=\"line\">123<\/span>\n<span class=\"line\">124<\/span>\n<span class=\"line\">125<\/span>\n<span class=\"line\">126<\/span>\n<span class=\"line\">127<\/span>\n<span class=\"line\">128<\/span>\n<span class=\"line\">129<\/span>\n<span class=\"line\">130<\/span>\n<span class=\"line\">131<\/span>\n<span class=\"line\">132<\/span>\n<span class=\"line\">133<\/span>\n<span class=\"line\">134<\/span>\n<span class=\"line\">135<\/span>\n<span class=\"line\">136<\/span>\n<span class=\"line\">137<\/span>\n<span class=\"line\">138<\/span>\n<span class=\"line\">139<\/span>\n<span class=\"line\">140<\/span>\n<span class=\"line\">141<\/span>\n<span class=\"line\">142<\/span>\n<span class=\"line\">143<\/span>\n<span class=\"line\">144<\/span>\n<span class=\"line\">145<\/span>\n<span class=\"line\">146<\/span>\n<span class=\"line\">147<\/span>\n<span class=\"line\">148<\/span>\n<span class=\"line\">149<\/span>\n<span class=\"line\">150<\/span>\n<span class=\"line\">151<\/span>\n<span class=\"line\">152<\/span>\n<span class=\"line\">153<\/span>\n<span class=\"line\">154<\/span>\n<span class=\"line\">155<\/span>\n<span class=\"line\">156<\/span>\n<span class=\"line\">157<\/span>\n<span class=\"line\">158<\/span>\n<span class=\"line\">159<\/span>\n<span class=\"line\">160<\/span>\n<span class=\"line\">161<\/span>\n<span class=\"line\">162<\/span>\n<span class=\"line\">163<\/span>\n<span class=\"line\">164<\/span>\n<span class=\"line\">165<\/span>\n<span class=\"line\">166<\/span>\n<span class=\"line\">167<\/span>\n<span class=\"line\">168<\/span>\n<span class=\"line\">169<\/span>\n<span class=\"line\">170<\/span>\n<span class=\"line\">171<\/span>\n<span class=\"line\">172<\/span>\n<span class=\"line\">173<\/span>\n<span class=\"line\">174<\/span>\n<span class=\"line\">175<\/span>\n<span class=\"line\">176<\/span>\n<span class=\"line\">177<\/span>\n<span class=\"line\">178<\/span>\n<span class=\"line\">179<\/span>\n<span class=\"line\">180<\/span>\n<span class=\"line\">181<\/span>\n<span class=\"line\">182<\/span>\n<span class=\"line\">183<\/span>\n<span class=\"line\">184<\/span>\n<span class=\"line\">185<\/span>\n<span class=\"line\">186<\/span>\n<span class=\"line\">187<\/span>\n<span class=\"line\">188<\/span>\n<span class=\"line\">189<\/span>\n<span class=\"line\">190<\/span>\n<span class=\"line\">191<\/span>\n<span class=\"line\">192<\/span>\n<span class=\"line\">193<\/span>\n<span class=\"line\">194<\/span>\n<span class=\"line\">195<\/span>\n<span class=\"line\">196<\/span>\n<span class=\"line\">197<\/span>\n<span class=\"line\">198<\/span>\n<span class=\"line\">199<\/span>\n<span class=\"line\">200<\/span>\n<span class=\"line\">201<\/span>\n<span class=\"line\">202<\/span>\n<span class=\"line\">203<\/span>\n<span class=\"line\">204<\/span>\n<span class=\"line\">205<\/span>\n<span class=\"line\">206<\/span>\n<span class=\"line\">207<\/span>\n<span class=\"line\">208<\/span>\n<span class=\"line\">209<\/span>\n<span class=\"line\">210<\/span>\n<span class=\"line\">211<\/span>\n<span class=\"line\">212<\/span>\n<span class=\"line\">213<\/span>\n<span class=\"line\">214<\/span>\n<span class=\"line\">215<\/span>\n<span class=\"line\">216<\/span>\n<span class=\"line\">217<\/span>\n<span class=\"line\">218<\/span>\n<span class=\"line\">219<\/span>\n<span class=\"line\">220<\/span>\n<span class=\"line\">221<\/span>\n<span class=\"line\">222<\/span>\n<span class=\"line\">223<\/span>\n<span class=\"line\">224<\/span>\n<span class=\"line\">225<\/span>\n<span class=\"line\">226<\/span>\n<span class=\"line\">227<\/span>\n<span class=\"line\">228<\/span>\n<span class=\"line\">229<\/span>\n<span class=\"line\">230<\/span>\n<span class=\"line\">231<\/span>\n<span class=\"line\">232<\/span>\n<span class=\"line\">233<\/span>\n<span class=\"line\">234<\/span>\n<span class=\"line\">235<\/span>\n<span class=\"line\">236<\/span>\n<span class=\"line\">237<\/span>\n<span class=\"line\">238<\/span>\n<span class=\"line\">239<\/span>\n<span class=\"line\">240<\/span>\n<span class=\"line\">241<\/span>\n<span class=\"line\">242<\/span>\n<span class=\"line\">243<\/span>\n<span class=\"line\">244<\/span>\n<span class=\"line\">245<\/span>\n<span class=\"line\">246<\/span>\n<span class=\"line\">247<\/span>\n<span class=\"line\">248<\/span>\n<span class=\"line\">249<\/span>\n<span class=\"line\">250<\/span>\n<span class=\"line\">251<\/span>\n<span class=\"line\">252<\/span>\n<span class=\"line\">253<\/span>\n<span class=\"line\">254<\/span>\n<span class=\"line\">255<\/span>\n<span class=\"line\">256<\/span>\n<span class=\"line\">257<\/span>\n<span class=\"line\">258<\/span>\n<span class=\"line\">259<\/span>\n<span class=\"line\">260<\/span>\n<span class=\"line\">261<\/span>\n<span class=\"line\">262<\/span>\n<span class=\"line\">263<\/span>\n<span class=\"line\">264<\/span>\n<span class=\"line\">265<\/span>\n<span class=\"line\">266<\/span>\n<span class=\"line\">267<\/span>\n<span class=\"line\">268<\/span>\n<span class=\"line\">269<\/span>\n<span class=\"line\">270<\/span>\n<span class=\"line\">271<\/span>\n<span class=\"line\">272<\/span>\n<span class=\"line\">273<\/span>\n<span class=\"line\">274<\/span>\n<span class=\"line\">275<\/span>\n<span class=\"line\">276<\/span>\n<span class=\"line\">277<\/span>\n<span class=\"line\">278<\/span>\n<span class=\"line\">279<\/span>\n<span class=\"line\">280<\/span>\n<span class=\"line\">281<\/span>\n<span class=\"line\">282<\/span>\n<span class=\"line\">283<\/span>\n<span class=\"line\">284<\/span>\n<span class=\"line\">285<\/span>\n<span class=\"line\">286<\/span>\n<span class=\"line\">287<\/span>\n<span class=\"line\">288<\/span>\n<span class=\"line\">289<\/span>\n<span class=\"line\">290<\/span>\n<span class=\"line\">291<\/span>\n<span class=\"line\">292<\/span>\n<span class=\"line\">293<\/span>\n<span class=\"line\">294<\/span>\n<span class=\"line\">295<\/span>\n<span class=\"line\">296<\/span>\n<span class=\"line\">297<\/span>\n<span class=\"line\">298<\/span>\n<span class=\"line\">299<\/span>\n<span class=\"line\">300<\/span>\n<span class=\"line\">301<\/span>\n<span class=\"line\">302<\/span>\n<span class=\"line\">303<\/span>\n<span class=\"line\">304<\/span>\n<span class=\"line\">305<\/span>\n<span class=\"line\">306<\/span>\n<span class=\"line\">307<\/span>\n<span class=\"line\">308<\/span>\n<span class=\"line\">309<\/span>\n<span class=\"line\">310<\/span>\n<span class=\"line\">311<\/span>\n<span class=\"line\">312<\/span>\n<span class=\"line\">313<\/span>\n<span class=\"line\">314<\/span>\n<span class=\"line\">315<\/span>\n<span class=\"line\">316<\/span>\n<span class=\"line\">317<\/span>\n<span class=\"line\">318<\/span>\n<span class=\"line\">319<\/span>\n<span class=\"line\">320<\/span>\n<span class=\"line\">321<\/span>\n<span class=\"line\">322<\/span>\n<span class=\"line\">323<\/span>\n<span class=\"line\">324<\/span>\n<span class=\"line\">325<\/span>\n<span class=\"line\">326<\/span>\n<span class=\"line\">327<\/span>\n<span class=\"line\">328<\/span>\n<span class=\"line\">329<\/span>\n<span class=\"line\">330<\/span>\n<span class=\"line\">331<\/span>\n<span class=\"line\">332<\/span>\n<span class=\"line\">333<\/span>\n<span class=\"line\">334<\/span>\n<span class=\"line\">335<\/span>\n<span class=\"line\">336<\/span>\n<span class=\"line\">337<\/span>\n<span class=\"line\">338<\/span>\n<span class=\"line\">339<\/span>\n<span class=\"line\">340<\/span>\n<span class=\"line\">341<\/span>\n<span class=\"line\">342<\/span>\n<span class=\"line\">343<\/span>\n<span class=\"line\">344<\/span>\n<span class=\"line\">345<\/span>\n<span class=\"line\">346<\/span>\n<span class=\"line\">347<\/span>\n<span class=\"line\">348<\/span>\n<span class=\"line\">349<\/span>\n<span class=\"line\">350<\/span>\n<span class=\"line\">351<\/span>\n<span class=\"line\">352<\/span>\n<span class=\"line\">353<\/span>\n<span class=\"line\">354<\/span>\n<span class=\"line\">355<\/span>\n<span class=\"line\">356<\/span>\n<span class=\"line\">357<\/span>\n<span class=\"line\">358<\/span>\n<span class=\"line\">359<\/span>\n<span class=\"line\">360<\/span>\n<span class=\"line\">361<\/span>\n<span class=\"line\">362<\/span>\n<span class=\"line\">363<\/span>\n<span class=\"line\">364<\/span>\n<span class=\"line\">365<\/span>\n<span class=\"line\">366<\/span>\n<span class=\"line\">367<\/span>\n<span class=\"line\">368<\/span>\n<span class=\"line\">369<\/span>\n<span class=\"line\">370<\/span>\n<span class=\"line\">371<\/span>\n<span class=\"line\">372<\/span>\n<span class=\"line\">373<\/span>\n<span class=\"line\">374<\/span>\n<span class=\"line\">375<\/span>\n<span class=\"line\">376<\/span>\n<span class=\"line\">377<\/span>\n<span class=\"line\">378<\/span>\n<span class=\"line\">379<\/span>\n<span class=\"line\">380<\/span>\n<span class=\"line\">381<\/span>\n<span class=\"line\">382<\/span>\n<span class=\"line\">383<\/span>\n<span class=\"line\">384<\/span>\n<span class=\"line\">385<\/span>\n<span class=\"line\">386<\/span>\n<span class=\"line\">387<\/span>\n<span class=\"line\">388<\/span>\n<span class=\"line\">389<\/span>\n<span class=\"line\">390<\/span>\n<span class=\"line\">391<\/span>\n<span class=\"line\">392<\/span>\n<span class=\"line\">393<\/span>\n<span class=\"line\">394<\/span>\n<span class=\"line\">395<\/span>\n<span class=\"line\">396<\/span>\n<span class=\"line\">397<\/span>\n<span class=\"line\">398<\/span>\n<span class=\"line\">399<\/span>\n<span class=\"line\">400<\/span>\n<span class=\"line\">401<\/span>\n<span class=\"line\">402<\/span>\n<span class=\"line\">403<\/span>\n<span class=\"line\">404<\/span>\n<span class=\"line\">405<\/span>\n<span class=\"line\">406<\/span>\n<span class=\"line\">407<\/span>\n<span class=\"line\">408<\/span>\n<span class=\"line\">409<\/span>\n<span class=\"line\">410<\/span>\n<span class=\"line\">411<\/span>\n<span class=\"line\">412<\/span>\n<span class=\"line\">413<\/span>\n<span class=\"line\">414<\/span>\n<span class=\"line\">415<\/span>\n<span class=\"line\">416<\/span>\n<span class=\"line\">417<\/span>\n<span class=\"line\">418<\/span>\n<span class=\"line\">419<\/span>\n<span class=\"line\">420<\/span>\n<span class=\"line\">421<\/span>\n<span class=\"line\">422<\/span>\n<span class=\"line\">423<\/span>\n<span class=\"line\">424<\/span>\n<span class=\"line\">425<\/span>\n<span class=\"line\">426<\/span>\n<span class=\"line\">427<\/span>\n<span class=\"line\">428<\/span>\n<span class=\"line\">429<\/span>\n<span class=\"line\">430<\/span>\n<span class=\"line\">431<\/span>\n<span class=\"line\">432<\/span>\n<span class=\"line\">433<\/span>\n<span class=\"line\">434<\/span>\n<span class=\"line\">435<\/span>\n<span class=\"line\">436<\/span>\n<span class=\"line\">437<\/span>\n<span class=\"line\">438<\/span>\n<span class=\"line\">439<\/span>\n<span class=\"line\">440<\/span>\n<span class=\"line\">441<\/span>\n<span class=\"line\">442<\/span>\n<span class=\"line\">443<\/span>\n<span class=\"line\">444<\/span>\n<span class=\"line\">445<\/span>\n<span class=\"line\">446<\/span>\n<span class=\"line\">447<\/span>\n<span class=\"line\">448<\/span>\n<span class=\"line\">449<\/span>\n<span class=\"line\">450<\/span>\n<span class=\"line\">451<\/span>\n<span class=\"line\">452<\/span>\n<span class=\"line\">453<\/span>\n<span class=\"line\">454<\/span>\n<span class=\"line\">455<\/span>\n<span class=\"line\">456<\/span>\n<span class=\"line\">457<\/span>\n<span class=\"line\">458<\/span>\n<span class=\"line\">459<\/span>\n<span class=\"line\">460<\/span>\n<span class=\"line\">461<\/span>\n<span class=\"line\">462<\/span>\n<span class=\"line\">463<\/span>\n<span class=\"line\">464<\/span>\n<span class=\"line\">465<\/span>\n<span class=\"line\">466<\/span>\n<span class=\"line\">467<\/span>\n<span class=\"line\">468<\/span>\n<span class=\"line\">469<\/span>\n<span class=\"line\">470<\/span>\n<span class=\"line\">471<\/span>\n<span class=\"line\">472<\/span>\n<span class=\"line\">473<\/span>\n<span class=\"line\">474<\/span>\n<span class=\"line\">475<\/span>\n<span class=\"line\">476<\/span>\n<span class=\"line\">477<\/span>\n<span class=\"line\">478<\/span>\n<span class=\"line\">479<\/span>\n<span class=\"line\">480<\/span>\n<span class=\"line\">481<\/span>\n<span class=\"line\">482<\/span>\n<span class=\"line\">483<\/span>\n<span class=\"line\">484<\/span>\n<span class=\"line\">485<\/span>\n<span class=\"line\">486<\/span>\n<span class=\"line\">487<\/span>\n<span class=\"line\">488<\/span>\n<span class=\"line\">489<\/span>\n<span class=\"line\">490<\/span>\n<span class=\"line\">491<\/span>\n<span class=\"line\">492<\/span>\n<span class=\"line\">493<\/span>\n<span class=\"line\">494<\/span>\n<span class=\"line\">495<\/span>\n<span class=\"line\">496<\/span>\n<span class=\"line\">497<\/span>\n<span class=\"line\">498<\/span>\n<span class=\"line\">499<\/span>\n<span class=\"line\">500<\/span>\n<span class=\"line\">501<\/span>\n<span class=\"line\">502<\/span>\n<span class=\"line\">503<\/span>\n<span class=\"line\">504<\/span>\n<span class=\"line\">505<\/span>\n<span class=\"line\">506<\/span>\n<span class=\"line\">507<\/span>\n<span class=\"line\">508<\/span>\n<span class=\"line\">509<\/span>\n<span class=\"line\">510<\/span>\n<span class=\"line\">511<\/span>\n<span class=\"line\">512<\/span>\n<span class=\"line\">513<\/span>\n<span class=\"line\">514<\/span>\n<span class=\"line\">515<\/span>\n<span class=\"line\">516<\/span>\n<span class=\"line\">517<\/span>\n<span class=\"line\">518<\/span>\n<span class=\"line\">519<\/span>\n<span class=\"line\">520<\/span>\n<span class=\"line\">521<\/span>\n<span class=\"line\">522<\/span>\n<span class=\"line\">523<\/span>\n<span class=\"line\">524<\/span>\n<span class=\"line\">525<\/span>\n<span class=\"line\">526<\/span>\n<span class=\"line\">527<\/span>\n<span class=\"line\">528<\/span>\n<span class=\"line\">529<\/span>\n<span class=\"line\">530<\/span>\n<span class=\"line\">531<\/span>\n<span class=\"line\">532<\/span>\n<span class=\"line\">533<\/span>\n<span class=\"line\">534<\/span>\n<span class=\"line\">535<\/span>\n<span class=\"line\">536<\/span>\n<span class=\"line\">537<\/span>\n<span class=\"line\">538<\/span>\n<span class=\"line\">539<\/span>\n<span class=\"line\">540<\/span>\n<span class=\"line\">541<\/span>\n<span class=\"line\">542<\/span>\n<span class=\"line\">543<\/span>\n<span class=\"line\">544<\/span>\n<span class=\"line\">545<\/span>\n<span class=\"line\">546<\/span>\n<span class=\"line\">547<\/span>\n<span class=\"line\">548<\/span>\n<span class=\"line\">549<\/span>\n<span class=\"line\">550<\/span>\n<span class=\"line\">551<\/span>\n<span class=\"line\">552<\/span>\n<span class=\"line\">553<\/span>\n<span class=\"line\">554<\/span>\n<span class=\"line\">555<\/span>\n<span class=\"line\">556<\/span>\n<span class=\"line\">557<\/span>\n<span class=\"line\">558<\/span>\n<span class=\"line\">559<\/span>\n<span class=\"line\">560<\/span>\n<span class=\"line\">561<\/span>\n<span class=\"line\">562<\/span>\n<span class=\"line\">563<\/span>\n<span class=\"line\">564<\/span>\n<span class=\"line\">565<\/span>\n<span class=\"line\">566<\/span>\n<span class=\"line\">567<\/span>\n<span class=\"line\">568<\/span>\n<span class=\"line\">569<\/span>\n<span class=\"line\">570<\/span>\n<span class=\"line\">571<\/span>\n<span class=\"line\">572<\/span>\n<span class=\"line\">573<\/span>\n<span class=\"line\">574<\/span>\n<span class=\"line\">575<\/span>\n<span class=\"line\">576<\/span>\n<span class=\"line\">577<\/span>\n<span class=\"line\">578<\/span>\n<span class=\"line\">579<\/span>\n<span class=\"line\">580<\/span>\n<span class=\"line\">581<\/span>\n<span class=\"line\">582<\/span>\n<span class=\"line\">583<\/span>\n<span class=\"line\">584<\/span>\n<span class=\"line\">585<\/span>\n<span class=\"line\">586<\/span>\n<span class=\"line\">587<\/span>\n<span class=\"line\">588<\/span>\n<span class=\"line\">589<\/span>\n<span class=\"line\">590<\/span>\n<span class=\"line\">591<\/span>\n<span class=\"line\">592<\/span>\n<span class=\"line\">593<\/span>\n<span class=\"line\">594<\/span>\n<span class=\"line\">595<\/span>\n<span class=\"line\">596<\/span>\n<span class=\"line\">597<\/span>\n<span class=\"line\">598<\/span>\n<span class=\"line\">599<\/span>\n<span class=\"line\">600<\/span>\n<span class=\"line\">601<\/span>\n<span class=\"line\">602<\/span>\n<span class=\"line\">603<\/span>\n<span class=\"line\">604<\/span>\n<span class=\"line\">605<\/span>\n<span class=\"line\">606<\/span>\n<span class=\"line\">607<\/span>\n<span class=\"line\">608<\/span>\n<span class=\"line\">609<\/span>\n<span class=\"line\">610<\/span>\n<span class=\"line\">611<\/span>\n<span class=\"line\">612<\/span>\n<span class=\"line\">613<\/span>\n<span class=\"line\">614<\/span>\n<span class=\"line\">615<\/span>\n<span class=\"line\">616<\/span>\n<span class=\"line\">617<\/span>\n<span class=\"line\">618<\/span>\n<span class=\"line\">619<\/span>\n<span class=\"line\">620<\/span>\n<span class=\"line\">621<\/span>\n<span class=\"line\">622<\/span>\n<span class=\"line\">623<\/span>\n<span class=\"line\">624<\/span>\n<span class=\"line\">625<\/span>\n<span class=\"line\">626<\/span>\n<span class=\"line\">627<\/span>\n<span class=\"line\">628<\/span>\n<span class=\"line\">629<\/span>\n<span class=\"line\">630<\/span>\n<span class=\"line\">631<\/span>\n<span class=\"line\">632<\/span>\n<span class=\"line\">633<\/span>\n<span class=\"line\">634<\/span>\n<span class=\"line\">635<\/span>\n<span class=\"line\">636<\/span>\n<span class=\"line\">637<\/span>\n<span class=\"line\">638<\/span>\n<span class=\"line\">639<\/span>\n<span class=\"line\">640<\/span>\n<span class=\"line\">641<\/span>\n<span class=\"line\">642<\/span>\n<span class=\"line\">643<\/span>\n<span class=\"line\">644<\/span>\n<span class=\"line\">645<\/span>\n<span class=\"line\">646<\/span>\n<span class=\"line\">647<\/span>\n<span class=\"line\">648<\/span>\n<span class=\"line\">649<\/span>\n<span class=\"line\">650<\/span>\n<span class=\"line\">651<\/span>\n<span class=\"line\">652<\/span>\n<span class=\"line\">653<\/span>\n<span class=\"line\">654<\/span>\n<span class=\"line\">655<\/span>\n<span class=\"line\">656<\/span>\n<span class=\"line\">657<\/span>\n<span class=\"line\">658<\/span>\n<span class=\"line\">659<\/span>\n<span class=\"line\">660<\/span>\n<span class=\"line\">661<\/span>\n<span class=\"line\">662<\/span>\n<span class=\"line\">663<\/span>\n<span class=\"line\">664<\/span>\n<span class=\"line\">665<\/span>\n<span class=\"line\">666<\/span>\n<span class=\"line\">667<\/span>\n<span class=\"line\">668<\/span>\n<span class=\"line\">669<\/span>\n<span class=\"line\">670<\/span>\n<span class=\"line\">671<\/span>\n<span class=\"line\">672<\/span>\n<span class=\"line\">673<\/span>\n<span class=\"line\">674<\/span>\n<span class=\"line\">675<\/span>\n<span class=\"line\">676<\/span>\n<span class=\"line\">677<\/span>\n<span class=\"line\">678<\/span>\n<span class=\"line\">679<\/span>\n<span class=\"line\">680<\/span>\n<span class=\"line\">681<\/span>\n<span class=\"line\">682<\/span>\n<span class=\"line\">683<\/span>\n<span class=\"line\">684<\/span>\n<span class=\"line\">685<\/span>\n<span class=\"line\">686<\/span>\n<span class=\"line\">687<\/span>\n<span class=\"line\">688<\/span>\n<span class=\"line\">689<\/span>\n<span class=\"line\">690<\/span>\n<span class=\"line\">691<\/span>\n<span class=\"line\">692<\/span>\n<span class=\"line\">693<\/span>\n<span class=\"line\">694<\/span>\n<span class=\"line\">695<\/span>\n<span class=\"line\">696<\/span>\n<span class=\"line\">697<\/span>\n<span class=\"line\">698<\/span>\n<span class=\"line\">699<\/span>\n<span class=\"line\">700<\/span>\n<span class=\"line\">701<\/span>\n<span class=\"line\">702<\/span>\n<span class=\"line\">703<\/span>\n<span class=\"line\">704<\/span>\n<span class=\"line\">705<\/span>\n<span class=\"line\">706<\/span>\n<span class=\"line\">707<\/span>\n<span class=\"line\">708<\/span>\n<span class=\"line\">709<\/span>\n<span class=\"line\">710<\/span>\n<span class=\"line\">711<\/span>\n<span class=\"line\">712<\/span>\n<span class=\"line\">713<\/span>\n<span class=\"line\">714<\/span>\n<span class=\"line\">715<\/span>\n<span class=\"line\">716<\/span>\n<span class=\"line\">717<\/span>\n<span class=\"line\">718<\/span>\n<span class=\"line\">719<\/span>\n<span class=\"line\">720<\/span>\n<span class=\"line\">721<\/span>\n<span class=\"line\">722<\/span>\n<span class=\"line\">723<\/span>\n<span class=\"line\">724<\/span>\n<span class=\"line\">725<\/span>\n<span class=\"line\">726<\/span>\n<span class=\"line\">727<\/span>\n<span class=\"line\">728<\/span>\n<span class=\"line\">729<\/span>\n<span class=\"line\">730<\/span>\n<span class=\"line\">731<\/span>\n<span class=\"line\">732<\/span>\n<span class=\"line\">733<\/span>\n<span class=\"line\">734<\/span>\n<span class=\"line\">735<\/span>\n<span class=\"line\">736<\/span>\n<span class=\"line\">737<\/span>\n<span class=\"line\">738<\/span>\n<span class=\"line\">739<\/span>\n<span class=\"line\">740<\/span>\n<span class=\"line\">741<\/span>\n<span class=\"line\">742<\/span>\n<span class=\"line\">743<\/span>\n<span class=\"line\">744<\/span>\n<span class=\"line\">745<\/span>\n<span class=\"line\">746<\/span>\n<span class=\"line\">747<\/span>\n<span class=\"line\">748<\/span>\n<span class=\"line\">749<\/span>\n<span class=\"line\">750<\/span>\n<span class=\"line\">751<\/span>\n<span class=\"line\">752<\/span>\n<span class=\"line\">753<\/span>\n<span class=\"line\">754<\/span>\n<span class=\"line\">755<\/span>\n<span class=\"line\">756<\/span>\n<span class=\"line\">757<\/span>\n<span class=\"line\">758<\/span>\n<span class=\"line\">759<\/span>\n<span class=\"line\">760<\/span>\n<span class=\"line\">761<\/span>\n<span class=\"line\">762<\/span>\n<span class=\"line\">763<\/span>\n<span class=\"line\">764<\/span>\n<span class=\"line\">765<\/span>\n<span class=\"line\">766<\/span>\n<span class=\"line\">767<\/span>\n<span class=\"line\">768<\/span>\n<span class=\"line\">769<\/span>\n<span class=\"line\">770<\/span>\n<span class=\"line\">771<\/span>\n<span class=\"line\">772<\/span>\n<span class=\"line\">773<\/span>\n<span class=\"line\">774<\/span>\n<span class=\"line\">775<\/span>\n<span class=\"line\">776<\/span>\n<span class=\"line\">777<\/span>\n<span class=\"line\">778<\/span>\n<span class=\"line\">779<\/span>\n<span class=\"line\">780<\/span>\n<span class=\"line\">781<\/span>\n<span class=\"line\">782<\/span>\n<span class=\"line\">783<\/span>\n<span class=\"line\">784<\/span>\n<span class=\"line\">785<\/span>\n<span class=\"line\">786<\/span>\n<span class=\"line\">787<\/span>\n<span class=\"line\">788<\/span>\n<span class=\"line\">789<\/span>\n<span class=\"line\">790<\/span>\n<span class=\"line\">791<\/span>\n<span class=\"line\">792<\/span>\n<span class=\"line\">793<\/span>\n<span class=\"line\">794<\/span>\n<span class=\"line\">795<\/span>\n<span class=\"line\">796<\/span>\n<span class=\"line\">797<\/span>\n<span class=\"line\">798<\/span><\/pre>\n<\/td>\n<td class=\"code\">\n<pre><span class=\"line\"><span class=\"comment\">\/\/ &lt;!--GAMFC--&gt;version base on commit 43fad05dcdae3b723c53c226f8181fc5bd47223e, time is 2023-06-22 15:20:02 UTC&lt;!--GAMFC-END--&gt;.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\/\/ @ts-ignore<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">import<\/span> { connect } <span class=\"keyword\">from<\/span> <span class=\"string\">'cloudflare:sockets'<\/span>;<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/\/ How to generate your own UUID:<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\/\/ [Windows] Press \"Win + R\", input cmd and run:  Powershell -NoExit -Command \"[guid]::NewGuid()\"<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">let<\/span> userID = <span class=\"string\">'77a571fb-4fd2-4b37-8596-1b7d9728bb5c'<\/span>;<\/span>\n\n<span class=\"line\"><span class=\"keyword\">const<\/span> proxyIPs = [<span class=\"string\">\"workers.cloudflare.cyou\"<\/span>];<span class=\"comment\">\/\/['cdn.xn--b6gac.eu.org', 'cdn-all.xn--b6gac.eu.org', 'edgetunnel.anycast.eu.org'];<\/span><\/span>\n\n<span class=\"line\"><span class=\"keyword\">let<\/span> proxyIP = proxyIPs[<span class=\"title class_\">Math<\/span>.<span class=\"title function_\">floor<\/span>(<span class=\"title class_\">Math<\/span>.<span class=\"title function_\">random<\/span>() * proxyIPs.<span class=\"property\">length<\/span>)];<\/span>\n\n<span class=\"line\"><span class=\"keyword\">let<\/span> dohURL = <span class=\"string\">'https:\/\/sky.rethinkdns.com\/1:-Pf_____9_8A_AMAIgE8kMABVDDmKOHTAKg='<\/span>; <span class=\"comment\">\/\/ https:\/\/cloudflare-dns.com\/dns-query or https:\/\/dns.google\/dns-query<\/span><\/span>\n\n<span class=\"line\"><span class=\"comment\">\/\/ v2board api environment variables (optional) deprecated, please use planetscale.com instead<\/span><\/span>\n\n<span class=\"line\"><span class=\"keyword\">if<\/span> (!<span class=\"title function_\">isValidUUID<\/span>(userID)) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">throw<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Error<\/span>(<span class=\"string\">'uuid is invalid'<\/span>);<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"keyword\">export<\/span> <span class=\"keyword\">default<\/span> {<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").Request<\/span>} <span class=\"variable\">request<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">{UUID: string, PROXYIP: string, DNS_RESOLVER_URL: string, NODE_ID: int, API_HOST: string, API_TOKEN: string<\/span>}} env<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").ExecutionContext<\/span>} <span class=\"variable\">ctx<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">Promise&lt;Response&gt;<\/span>}<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t *\/<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">async<\/span> <span class=\"title function_\">fetch<\/span>(<span class=\"params\">request, env, ctx<\/span>) {<\/span>\n<span class=\"line\">\t\t<span class=\"comment\">\/\/ uuid_validator(request);<\/span><\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">try<\/span> {<\/span>\n<span class=\"line\">\t\t\tuserID = env.<span class=\"property\">UUID<\/span> || userID;<\/span>\n<span class=\"line\">\t\t\tproxyIP = env.<span class=\"property\">PROXYIP<\/span> || proxyIP;<\/span>\n<span class=\"line\">\t\t\tdohURL = env.<span class=\"property\">DNS_RESOLVER_URL<\/span> || dohURL;<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">let<\/span> userID_Path = userID;<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (userID.<span class=\"title function_\">includes<\/span>(<span class=\"string\">','<\/span>)) {<\/span>\n<span class=\"line\">\t\t\t\tuserID_Path = userID.<span class=\"title function_\">split<\/span>(<span class=\"string\">','<\/span>)[<span class=\"number\">0<\/span>];<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> upgradeHeader = request.<span class=\"property\">headers<\/span>.<span class=\"title function_\">get<\/span>(<span class=\"string\">'Upgrade'<\/span>);<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (!upgradeHeader || upgradeHeader !== <span class=\"string\">'websocket'<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> url = <span class=\"keyword\">new<\/span> <span class=\"title function_\">URL<\/span>(request.<span class=\"property\">url<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">switch<\/span> (url.<span class=\"property\">pathname<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"keyword\">case<\/span> <span class=\"string\">`\/cf`<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Response<\/span>(<span class=\"title class_\">JSON<\/span>.<span class=\"title function_\">stringify<\/span>(request.<span class=\"property\">cf<\/span>, <span class=\"literal\">null<\/span>, <span class=\"number\">4<\/span>), {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">status<\/span>: <span class=\"number\">200<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">headers<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t\t<span class=\"string\">\"Content-Type\"<\/span>: <span class=\"string\">\"application\/json;charset=utf-8\"<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t},<\/span>\n<span class=\"line\">\t\t\t\t\t\t});<\/span>\n<span class=\"line\">\t\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"keyword\">case<\/span> <span class=\"string\">`\/<span class=\"subst\">${userID_Path}<\/span>`<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> vlessConfig = <span class=\"title function_\">getVLESSConfig<\/span>(userID, request.<span class=\"property\">headers<\/span>.<span class=\"title function_\">get<\/span>(<span class=\"string\">'Host'<\/span>));<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Response<\/span>(<span class=\"string\">`<span class=\"subst\">${vlessConfig}<\/span>`<\/span>, {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">status<\/span>: <span class=\"number\">200<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">headers<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t\t<span class=\"string\">\"Content-Type\"<\/span>: <span class=\"string\">\"text\/html; charset=utf-8\"<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t\t\t\t});<\/span>\n<span class=\"line\">\t\t\t\t\t};<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"keyword\">case<\/span> <span class=\"string\">`\/sub\/<span class=\"subst\">${userID_Path}<\/span>`<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> url = <span class=\"keyword\">new<\/span> <span class=\"title function_\">URL<\/span>(request.<span class=\"property\">url<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> searchParams = url.<span class=\"property\">searchParams<\/span>;<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> vlessSubConfig = <span class=\"title function_\">createVLESSSub<\/span>(userID, request.<span class=\"property\">headers<\/span>.<span class=\"title function_\">get<\/span>(<span class=\"string\">'Host'<\/span>));<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ Construct and return response object<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Response<\/span>(<span class=\"title function_\">btoa<\/span>(vlessSubConfig), {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">status<\/span>: <span class=\"number\">200<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">headers<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t\t<span class=\"string\">\"Content-Type\"<\/span>: <span class=\"string\">\"text\/plain;charset=utf-8\"<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t\t\t\t});<\/span>\n<span class=\"line\">\t\t\t\t\t};<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"attr\">default<\/span>:<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ return new Response('Not found', { status: 404 });<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ For any other path, reverse proxy to 'ramdom website' and return the original response, caching it in the process<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> randomHostname = cn_hostnames[<span class=\"title class_\">Math<\/span>.<span class=\"title function_\">floor<\/span>(<span class=\"title class_\">Math<\/span>.<span class=\"title function_\">random<\/span>() * cn_hostnames.<span class=\"property\">length<\/span>)];<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> newHeaders = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Headers<\/span>(request.<span class=\"property\">headers<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t\tnewHeaders.<span class=\"title function_\">set<\/span>(<span class=\"string\">'cf-connecting-ip'<\/span>, <span class=\"string\">'1.2.3.4'<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t\tnewHeaders.<span class=\"title function_\">set<\/span>(<span class=\"string\">'x-forwarded-for'<\/span>, <span class=\"string\">'1.2.3.4'<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t\tnewHeaders.<span class=\"title function_\">set<\/span>(<span class=\"string\">'x-real-ip'<\/span>, <span class=\"string\">'1.2.3.4'<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t\tnewHeaders.<span class=\"title function_\">set<\/span>(<span class=\"string\">'referer'<\/span>, <span class=\"string\">'https:\/\/www.google.com\/search?q=edtunnel'<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ Use fetch to proxy the request to 15 different domains<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> proxyUrl = <span class=\"string\">'https:\/\/'<\/span> + randomHostname + url.<span class=\"property\">pathname<\/span> + url.<span class=\"property\">search<\/span>;<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">let<\/span> modifiedRequest = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Request<\/span>(proxyUrl, {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">method<\/span>: request.<span class=\"property\">method<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">headers<\/span>: newHeaders,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">body<\/span>: request.<span class=\"property\">body<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"attr\">redirect<\/span>: <span class=\"string\">'manual'<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t});<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">const<\/span> proxyResponse = <span class=\"keyword\">await<\/span> <span class=\"title function_\">fetch<\/span>(modifiedRequest, { <span class=\"attr\">redirect<\/span>: <span class=\"string\">'manual'<\/span> });<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ Check for 302 or 301 redirect status and return an error response<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">if<\/span> ([<span class=\"number\">301<\/span>, <span class=\"number\">302<\/span>].<span class=\"title function_\">includes<\/span>(proxyResponse.<span class=\"property\">status<\/span>)) {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Response<\/span>(<span class=\"string\">`Redirects to <span class=\"subst\">${randomHostname}<\/span> are not allowed.`<\/span>, {<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t\t<span class=\"attr\">status<\/span>: <span class=\"number\">403<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t\t<span class=\"attr\">statusText<\/span>: <span class=\"string\">'Forbidden'<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t});<\/span>\n<span class=\"line\">\t\t\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ Return the response from the proxy server<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"keyword\">return<\/span> proxyResponse;<\/span>\n<span class=\"line\">\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t} <span class=\"keyword\">else<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">await<\/span> <span class=\"title function_\">vlessOverWSHandler<\/span>(request);<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t} <span class=\"keyword\">catch<\/span> (err) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/** <span class=\"doctag\">@type<\/span> {<span class=\"type\">Error<\/span>} *\/<\/span> <span class=\"keyword\">let<\/span> e = err;<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Response<\/span>(e.<span class=\"title function_\">toString<\/span>());<\/span>\n<span class=\"line\">\t\t}<\/span>\n<span class=\"line\">\t},<\/span>\n<span class=\"line\">};<\/span>\n\n<span class=\"line\"><span class=\"keyword\">export<\/span> <span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">uuid_validator<\/span>(<span class=\"params\">request<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> hostname = request.<span class=\"property\">headers<\/span>.<span class=\"title function_\">get<\/span>(<span class=\"string\">'Host'<\/span>);<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> currentDate = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Date<\/span>();<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> subdomain = hostname.<span class=\"title function_\">split<\/span>(<span class=\"string\">'.'<\/span>)[<span class=\"number\">0<\/span>];<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> year = currentDate.<span class=\"title function_\">getFullYear<\/span>();<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> month = <span class=\"title class_\">String<\/span>(currentDate.<span class=\"title function_\">getMonth<\/span>() + <span class=\"number\">1<\/span>).<span class=\"title function_\">padStart<\/span>(<span class=\"number\">2<\/span>, <span class=\"string\">'0'<\/span>);<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> day = <span class=\"title class_\">String<\/span>(currentDate.<span class=\"title function_\">getDate<\/span>()).<span class=\"title function_\">padStart<\/span>(<span class=\"number\">2<\/span>, <span class=\"string\">'0'<\/span>);<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> formattedDate = <span class=\"string\">`<span class=\"subst\">${year}<\/span>-<span class=\"subst\">${month}<\/span>-<span class=\"subst\">${day}<\/span>`<\/span>;<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ const daliy_sub = formattedDate + subdomain<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> hashHex = <span class=\"keyword\">await<\/span> <span class=\"title function_\">hashHex_f<\/span>(subdomain);<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ subdomain string contains timestamps utc and uuid string TODO.<\/span><\/span>\n<span class=\"line\">\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">log<\/span>(hashHex, subdomain, formattedDate);<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"keyword\">export<\/span> <span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">hashHex_f<\/span>(<span class=\"params\">string<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> encoder = <span class=\"keyword\">new<\/span> <span class=\"title class_\">TextEncoder<\/span>();<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> data = encoder.<span class=\"title function_\">encode<\/span>(string);<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> hashBuffer = <span class=\"keyword\">await<\/span> crypto.<span class=\"property\">subtle<\/span>.<span class=\"title function_\">digest<\/span>(<span class=\"string\">'SHA-256'<\/span>, data);<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> hashArray = <span class=\"title class_\">Array<\/span>.<span class=\"title function_\">from<\/span>(<span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(hashBuffer));<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> hashHex = hashArray.<span class=\"title function_\">map<\/span>(<span class=\"function\"><span class=\"params\">byte<\/span> =&gt;<\/span> byte.<span class=\"title function_\">toString<\/span>(<span class=\"number\">16<\/span>).<span class=\"title function_\">padStart<\/span>(<span class=\"number\">2<\/span>, <span class=\"string\">'0'<\/span>)).<span class=\"title function_\">join<\/span>(<span class=\"string\">''<\/span>);<\/span>\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> hashHex;<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Handles VLESS over WebSocket requests by creating a WebSocket pair, accepting the WebSocket connection, and processing the VLESS header.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").Request<\/span>} request The incoming request object.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">Promise&lt;Response&gt;<\/span>} A Promise that resolves to a WebSocket response object.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">vlessOverWSHandler<\/span>(<span class=\"params\">request<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> webSocketPair = <span class=\"keyword\">new<\/span> <span class=\"title class_\">WebSocketPair<\/span>();<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> [client, webSocket] = <span class=\"title class_\">Object<\/span>.<span class=\"title function_\">values<\/span>(webSocketPair);<\/span>\n<span class=\"line\">\twebSocket.<span class=\"title function_\">accept<\/span>();<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> address = <span class=\"string\">''<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> portWithRandomLog = <span class=\"string\">''<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> currentDate = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Date<\/span>();<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> <span class=\"title function_\">log<\/span> = (<span class=\"params\"><span class=\"comment\">\/** <span class=\"doctag\">@type<\/span> {<span class=\"type\">string<\/span>} *\/<\/span> info, <span class=\"comment\">\/** <span class=\"doctag\">@type<\/span> {<span class=\"type\">string | undefined<\/span>} *\/<\/span> event<\/span>) =&gt; {<\/span>\n<span class=\"line\">\t\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">log<\/span>(<span class=\"string\">`[<span class=\"subst\">${currentDate}<\/span> <span class=\"subst\">${address}<\/span>:<span class=\"subst\">${portWithRandomLog}<\/span>] <span class=\"subst\">${info}<\/span>`<\/span>, event || <span class=\"string\">''<\/span>);<\/span>\n<span class=\"line\">\t};<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> earlyDataHeader = request.<span class=\"property\">headers<\/span>.<span class=\"title function_\">get<\/span>(<span class=\"string\">'sec-websocket-protocol'<\/span>) || <span class=\"string\">''<\/span>;<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> readableWebSocketStream = <span class=\"title function_\">makeReadableWebSocketStream<\/span>(webSocket, earlyDataHeader, log);<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/** <span class=\"doctag\">@type<\/span> {<span class=\"type\">{ value: import(\"@cloudflare\/workers-types\").Socket | null<\/span>}}*\/<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> remoteSocketWapper = {<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">value<\/span>: <span class=\"literal\">null<\/span>,<\/span>\n<span class=\"line\">\t};<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> udpStreamWrite = <span class=\"literal\">null<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> isDns = <span class=\"literal\">false<\/span>;<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ ws --&gt; remote<\/span><\/span>\n<span class=\"line\">\treadableWebSocketStream.<span class=\"title function_\">pipeTo<\/span>(<span class=\"keyword\">new<\/span> <span class=\"title class_\">WritableStream<\/span>({<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">async<\/span> <span class=\"title function_\">write<\/span>(<span class=\"params\">chunk, controller<\/span>) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (isDns &amp;&amp; udpStreamWrite) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">return<\/span> <span class=\"title function_\">udpStreamWrite<\/span>(chunk);<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (remoteSocketWapper.<span class=\"property\">value<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> writer = remoteSocketWapper.<span class=\"property\">value<\/span>.<span class=\"property\">writable<\/span>.<span class=\"title function_\">getWriter<\/span>()<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">await<\/span> writer.<span class=\"title function_\">write<\/span>(chunk);<\/span>\n<span class=\"line\">\t\t\t\twriter.<span class=\"title function_\">releaseLock<\/span>();<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">return<\/span>;<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> {<\/span>\n<span class=\"line\">\t\t\t\thasError,<\/span>\n<span class=\"line\">\t\t\t\tmessage,<\/span>\n<span class=\"line\">\t\t\t\tportRemote = <span class=\"number\">443<\/span>,<\/span>\n<span class=\"line\">\t\t\t\taddressRemote = <span class=\"string\">''<\/span>,<\/span>\n<span class=\"line\">\t\t\t\trawDataIndex,<\/span>\n<span class=\"line\">\t\t\t\tvlessVersion = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>([<span class=\"number\">0<\/span>, <span class=\"number\">0<\/span>]),<\/span>\n<span class=\"line\">\t\t\t\tisUDP,<\/span>\n<span class=\"line\">\t\t\t} = <span class=\"title function_\">processVlessHeader<\/span>(chunk, userID);<\/span>\n<span class=\"line\">\t\t\taddress = addressRemote;<\/span>\n<span class=\"line\">\t\t\tportWithRandomLog = <span class=\"string\">`<span class=\"subst\">${portRemote}<\/span> <span class=\"subst\">${isUDP ? 'udp' : 'tcp'}<\/span> `<\/span>;<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (hasError) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"comment\">\/\/ controller.error(message);<\/span><\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">throw<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Error<\/span>(message); <span class=\"comment\">\/\/ cf seems has bug, controller.error will not end stream<\/span><\/span>\n<span class=\"line\">\t\t\t\t<span class=\"comment\">\/\/ webSocket.close(1000, message);<\/span><\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">return<\/span>;<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ If UDP and not DNS port, close it<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (isUDP &amp;&amp; portRemote !== <span class=\"number\">53<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">throw<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Error<\/span>(<span class=\"string\">'UDP proxy only enabled for DNS which is port 53'<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"comment\">\/\/ cf seems has bug, controller.error will not end stream<\/span><\/span>\n<span class=\"line\">\t\t\t}<\/span>\n\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (isUDP &amp;&amp; portRemote === <span class=\"number\">53<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\tisDns = <span class=\"literal\">true<\/span>;<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ [\"version\", \"\u9644\u52a0\u4fe1\u606f\u957f\u5ea6 N\"]<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> vlessResponseHeader = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>([vlessVersion[<span class=\"number\">0<\/span>], <span class=\"number\">0<\/span>]);<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> rawClientData = chunk.<span class=\"title function_\">slice<\/span>(rawDataIndex);<\/span>\n\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ <span class=\"doctag\">TODO:<\/span> support udp here when cf runtime has udp support<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (isDns) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> { write } = <span class=\"keyword\">await<\/span> <span class=\"title function_\">handleUDPOutBound<\/span>(webSocket, vlessResponseHeader, log);<\/span>\n<span class=\"line\">\t\t\t\tudpStreamWrite = write;<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">udpStreamWrite<\/span>(rawClientData);<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">return<\/span>;<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">handleTCPOutBound<\/span>(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log);<\/span>\n<span class=\"line\">\t\t},<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">close<\/span>() {<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`readableWebSocketStream is close`<\/span>);<\/span>\n<span class=\"line\">\t\t},<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">abort<\/span>(<span class=\"params\">reason<\/span>) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`readableWebSocketStream is abort`<\/span>, <span class=\"title class_\">JSON<\/span>.<span class=\"title function_\">stringify<\/span>(reason));<\/span>\n<span class=\"line\">\t\t},<\/span>\n<span class=\"line\">\t})).<span class=\"title function_\">catch<\/span>(<span class=\"function\">(<span class=\"params\">err<\/span>) =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">'readableWebSocketStream pipeTo error'<\/span>, err);<\/span>\n<span class=\"line\">\t});<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Response<\/span>(<span class=\"literal\">null<\/span>, {<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">status<\/span>: <span class=\"number\">101<\/span>,<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">webSocket<\/span>: client,<\/span>\n<span class=\"line\">\t});<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Handles outbound TCP connections.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">any<\/span>} remoteSocket <\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} addressRemote The remote address to connect to.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">number<\/span>} portRemote The remote port to connect to.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">Uint8Array<\/span>} rawClientData The raw client data to write.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").WebSocket<\/span>} webSocket The WebSocket to pass the remote socket to.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">Uint8Array<\/span>} vlessResponseHeader The VLESS response header.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">function<\/span>} log The logging function.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">Promise&lt;void&gt;<\/span>} The remote socket.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">handleTCPOutBound<\/span>(<span class=\"params\">remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log,<\/span>) {<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * Connects to a given address and port and writes data to the socket.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} address The address to connect to.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">number<\/span>} port The port to connect to.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">Promise&lt;import(\"@cloudflare\/workers-types\").Socket&gt;<\/span>} A Promise that resolves to the connected socket.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t *\/<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">connectAndWrite<\/span>(<span class=\"params\">address, port<\/span>) {<\/span>\n<span class=\"line\">\t\t<span class=\"comment\">\/** <span class=\"doctag\">@type<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").Socket<\/span>} *\/<\/span><\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">const<\/span> tcpSocket = <span class=\"title function_\">connect<\/span>({<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">hostname<\/span>: address,<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">port<\/span>: port,<\/span>\n<span class=\"line\">\t\t});<\/span>\n<span class=\"line\">\t\tremoteSocket.<span class=\"property\">value<\/span> = tcpSocket;<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`connected to <span class=\"subst\">${address}<\/span>:<span class=\"subst\">${port}<\/span>`<\/span>);<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">const<\/span> writer = tcpSocket.<span class=\"property\">writable<\/span>.<span class=\"title function_\">getWriter<\/span>();<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">await<\/span> writer.<span class=\"title function_\">write<\/span>(rawClientData); <span class=\"comment\">\/\/ first write, nomal is tls client hello<\/span><\/span>\n<span class=\"line\">\t\twriter.<span class=\"title function_\">releaseLock<\/span>();<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> tcpSocket;<\/span>\n<span class=\"line\">\t}<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * Retries connecting to the remote address and port if the Cloudflare socket has no incoming data.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">Promise&lt;void&gt;<\/span>} A Promise that resolves when the retry is complete.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t *\/<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">retry<\/span>() {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">const<\/span> tcpSocket = <span class=\"keyword\">await<\/span> <span class=\"title function_\">connectAndWrite<\/span>(proxyIP || addressRemote, portRemote)<\/span>\n<span class=\"line\">\t\ttcpSocket.<span class=\"property\">closed<\/span>.<span class=\"title function_\">catch<\/span>(<span class=\"function\"><span class=\"params\">error<\/span> =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">log<\/span>(<span class=\"string\">'retry tcpSocket closed error'<\/span>, error);<\/span>\n<span class=\"line\">\t\t}).<span class=\"title function_\">finally<\/span>(<span class=\"function\">() =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">safeCloseWebSocket<\/span>(webSocket);<\/span>\n<span class=\"line\">\t\t})<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">remoteSocketToWS<\/span>(tcpSocket, webSocket, vlessResponseHeader, <span class=\"literal\">null<\/span>, log);<\/span>\n<span class=\"line\">\t}<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> tcpSocket = <span class=\"keyword\">await<\/span> <span class=\"title function_\">connectAndWrite<\/span>(addressRemote, portRemote);<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ when remoteSocket is ready, pass to websocket<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ remote--&gt; ws<\/span><\/span>\n<span class=\"line\">\t<span class=\"title function_\">remoteSocketToWS<\/span>(tcpSocket, webSocket, vlessResponseHeader, retry, log);<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Creates a readable stream from a WebSocket server, allowing for data to be read from the WebSocket.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").WebSocket<\/span>} webSocketServer The WebSocket server to create the readable stream from.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} earlyDataHeader The header containing early data for WebSocket 0-RTT.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">(info: string)=&gt; void<\/span>} log The logging function.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">ReadableStream<\/span>} A readable stream that can be used to read data from the WebSocket.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">makeReadableWebSocketStream<\/span>(<span class=\"params\">webSocketServer, earlyDataHeader, log<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> readableStreamCancel = <span class=\"literal\">false<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> stream = <span class=\"keyword\">new<\/span> <span class=\"title class_\">ReadableStream<\/span>({<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">start<\/span>(<span class=\"params\">controller<\/span>) {<\/span>\n<span class=\"line\">\t\t\twebSocketServer.<span class=\"title function_\">addEventListener<\/span>(<span class=\"string\">'message'<\/span>, <span class=\"function\">(<span class=\"params\">event<\/span>) =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> message = event.<span class=\"property\">data<\/span>;<\/span>\n<span class=\"line\">\t\t\t\tcontroller.<span class=\"title function_\">enqueue<\/span>(message);<\/span>\n<span class=\"line\">\t\t\t});<\/span>\n\n<span class=\"line\">\t\t\twebSocketServer.<span class=\"title function_\">addEventListener<\/span>(<span class=\"string\">'close'<\/span>, <span class=\"function\">() =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">safeCloseWebSocket<\/span>(webSocketServer);<\/span>\n<span class=\"line\">\t\t\t\tcontroller.<span class=\"title function_\">close<\/span>();<\/span>\n<span class=\"line\">\t\t\t});<\/span>\n\n<span class=\"line\">\t\t\twebSocketServer.<span class=\"title function_\">addEventListener<\/span>(<span class=\"string\">'error'<\/span>, <span class=\"function\">(<span class=\"params\">err<\/span>) =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">'webSocketServer has error'<\/span>);<\/span>\n<span class=\"line\">\t\t\t\tcontroller.<span class=\"title function_\">error<\/span>(err);<\/span>\n<span class=\"line\">\t\t\t});<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> { earlyData, error } = <span class=\"title function_\">base64ToArrayBuffer<\/span>(earlyDataHeader);<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (error) {<\/span>\n<span class=\"line\">\t\t\t\tcontroller.<span class=\"title function_\">error<\/span>(error);<\/span>\n<span class=\"line\">\t\t\t} <span class=\"keyword\">else<\/span> <span class=\"keyword\">if<\/span> (earlyData) {<\/span>\n<span class=\"line\">\t\t\t\tcontroller.<span class=\"title function_\">enqueue<\/span>(earlyData);<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t},<\/span>\n\n<span class=\"line\">\t\t<span class=\"title function_\">pull<\/span>(<span class=\"params\">controller<\/span>) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ if ws can stop read if stream is full, we can implement backpressure<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ https:\/\/streams.spec.whatwg.org\/#example-rs-push-backpressure<\/span><\/span>\n<span class=\"line\">\t\t},<\/span>\n\n<span class=\"line\">\t\t<span class=\"title function_\">cancel<\/span>(<span class=\"params\">reason<\/span>) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`ReadableStream was canceled, due to <span class=\"subst\">${reason}<\/span>`<\/span>)<\/span>\n<span class=\"line\">\t\t\treadableStreamCancel = <span class=\"literal\">true<\/span>;<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">safeCloseWebSocket<\/span>(webSocketServer);<\/span>\n<span class=\"line\">\t\t}<\/span>\n<span class=\"line\">\t});<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> stream;<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/\/ https:\/\/xtls.github.io\/development\/protocols\/vless.html<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\/\/ https:\/\/github.com\/zizifn\/excalidraw-backup\/blob\/main\/v2ray-protocol.excalidraw<\/span><\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Processes the VLESS header buffer and returns an object with the relevant information.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">ArrayBuffer<\/span>} vlessBuffer The VLESS header buffer to process.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} userID The user ID to validate against the UUID in the VLESS header.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">{<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  hasError: boolean,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  message?: string,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  addressRemote?: string,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  addressType?: number,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  portRemote?: number,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  rawDataIndex?: number,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  vlessVersion?: Uint8Array,<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> *  isUDP?: boolean<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"type\"><span class=\"comment\"> * <\/span>}} An object with the relevant information extracted from the VLESS header buffer.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">processVlessHeader<\/span>(<span class=\"params\">vlessBuffer, userID<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (vlessBuffer.<span class=\"property\">byteLength<\/span> &lt; <span class=\"number\">24<\/span>) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">hasError<\/span>: <span class=\"literal\">true<\/span>,<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">message<\/span>: <span class=\"string\">'invalid data'<\/span>,<\/span>\n<span class=\"line\">\t\t};<\/span>\n<span class=\"line\">\t}<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> version = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(vlessBuffer.<span class=\"title function_\">slice<\/span>(<span class=\"number\">0<\/span>, <span class=\"number\">1<\/span>));<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> isValidUser = <span class=\"literal\">false<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> isUDP = <span class=\"literal\">false<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> slicedBuffer = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(vlessBuffer.<span class=\"title function_\">slice<\/span>(<span class=\"number\">1<\/span>, <span class=\"number\">17<\/span>));<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> slicedBufferString = <span class=\"title function_\">stringify<\/span>(slicedBuffer);<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ check if userID is valid uuid or uuids split by , and contains userID in it otherwise return error message to console<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> uuids = userID.<span class=\"title function_\">includes<\/span>(<span class=\"string\">','<\/span>) ? userID.<span class=\"title function_\">split<\/span>(<span class=\"string\">\",\"<\/span>) : [userID];<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ uuid_validator(hostName, slicedBufferString);<\/span><\/span>\n\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ isValidUser = uuids.some(userUuid =&gt; slicedBufferString === userUuid.trim());<\/span><\/span>\n<span class=\"line\">\tisValidUser = uuids.<span class=\"title function_\">some<\/span>(<span class=\"function\"><span class=\"params\">userUuid<\/span> =&gt;<\/span> slicedBufferString === userUuid.<span class=\"title function_\">trim<\/span>()) || uuids.<span class=\"property\">length<\/span> === <span class=\"number\">1<\/span> &amp;&amp; slicedBufferString === uuids[<span class=\"number\">0<\/span>].<span class=\"title function_\">trim<\/span>();<\/span>\n\n<span class=\"line\">\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">log<\/span>(<span class=\"string\">`userID: <span class=\"subst\">${slicedBufferString}<\/span>`<\/span>);<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (!isValidUser) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">hasError<\/span>: <span class=\"literal\">true<\/span>,<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">message<\/span>: <span class=\"string\">'invalid user'<\/span>,<\/span>\n<span class=\"line\">\t\t};<\/span>\n<span class=\"line\">\t}<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> optLength = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(vlessBuffer.<span class=\"title function_\">slice<\/span>(<span class=\"number\">17<\/span>, <span class=\"number\">18<\/span>))[<span class=\"number\">0<\/span>];<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/skip opt for now<\/span><\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> command = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(<\/span>\n<span class=\"line\">\t\tvlessBuffer.<span class=\"title function_\">slice<\/span>(<span class=\"number\">18<\/span> + optLength, <span class=\"number\">18<\/span> + optLength + <span class=\"number\">1<\/span>)<\/span>\n<span class=\"line\">\t)[<span class=\"number\">0<\/span>];<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ 0x01 TCP<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ 0x02 UDP<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ 0x03 MUX<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (command === <span class=\"number\">1<\/span>) {<\/span>\n<span class=\"line\">\t\tisUDP = <span class=\"literal\">false<\/span>;<\/span>\n<span class=\"line\">\t} <span class=\"keyword\">else<\/span> <span class=\"keyword\">if<\/span> (command === <span class=\"number\">2<\/span>) {<\/span>\n<span class=\"line\">\t\tisUDP = <span class=\"literal\">true<\/span>;<\/span>\n<span class=\"line\">\t} <span class=\"keyword\">else<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">hasError<\/span>: <span class=\"literal\">true<\/span>,<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">message<\/span>: <span class=\"string\">`command <span class=\"subst\">${command}<\/span> is not support, command 01-tcp,02-udp,03-mux`<\/span>,<\/span>\n<span class=\"line\">\t\t};<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> portIndex = <span class=\"number\">18<\/span> + optLength + <span class=\"number\">1<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> portBuffer = vlessBuffer.<span class=\"title function_\">slice<\/span>(portIndex, portIndex + <span class=\"number\">2<\/span>);<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ port is big-Endian in raw data etc 80 == 0x005d<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> portRemote = <span class=\"keyword\">new<\/span> <span class=\"title class_\">DataView<\/span>(portBuffer).<span class=\"title function_\">getUint16<\/span>(<span class=\"number\">0<\/span>);<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> addressIndex = portIndex + <span class=\"number\">2<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> addressBuffer = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(<\/span>\n<span class=\"line\">\t\tvlessBuffer.<span class=\"title function_\">slice<\/span>(addressIndex, addressIndex + <span class=\"number\">1<\/span>)<\/span>\n<span class=\"line\">\t);<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ 1--&gt; ipv4  addressLength =4<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ 2--&gt; domain name addressLength=addressBuffer[1]<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ 3--&gt; ipv6  addressLength =16<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> addressType = addressBuffer[<span class=\"number\">0<\/span>];<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> addressLength = <span class=\"number\">0<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> addressValueIndex = addressIndex + <span class=\"number\">1<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> addressValue = <span class=\"string\">''<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">switch<\/span> (addressType) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">case<\/span> <span class=\"number\">1<\/span>:<\/span>\n<span class=\"line\">\t\t\taddressLength = <span class=\"number\">4<\/span>;<\/span>\n<span class=\"line\">\t\t\taddressValue = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(<\/span>\n<span class=\"line\">\t\t\t\tvlessBuffer.<span class=\"title function_\">slice<\/span>(addressValueIndex, addressValueIndex + addressLength)<\/span>\n<span class=\"line\">\t\t\t).<span class=\"title function_\">join<\/span>(<span class=\"string\">'.'<\/span>);<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">break<\/span>;<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">case<\/span> <span class=\"number\">2<\/span>:<\/span>\n<span class=\"line\">\t\t\taddressLength = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(<\/span>\n<span class=\"line\">\t\t\t\tvlessBuffer.<span class=\"title function_\">slice<\/span>(addressValueIndex, addressValueIndex + <span class=\"number\">1<\/span>)<\/span>\n<span class=\"line\">\t\t\t)[<span class=\"number\">0<\/span>];<\/span>\n<span class=\"line\">\t\t\taddressValueIndex += <span class=\"number\">1<\/span>;<\/span>\n<span class=\"line\">\t\t\taddressValue = <span class=\"keyword\">new<\/span> <span class=\"title class_\">TextDecoder<\/span>().<span class=\"title function_\">decode<\/span>(<\/span>\n<span class=\"line\">\t\t\t\tvlessBuffer.<span class=\"title function_\">slice<\/span>(addressValueIndex, addressValueIndex + addressLength)<\/span>\n<span class=\"line\">\t\t\t);<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">break<\/span>;<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">case<\/span> <span class=\"number\">3<\/span>:<\/span>\n<span class=\"line\">\t\t\taddressLength = <span class=\"number\">16<\/span>;<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> dataView = <span class=\"keyword\">new<\/span> <span class=\"title class_\">DataView<\/span>(<\/span>\n<span class=\"line\">\t\t\t\tvlessBuffer.<span class=\"title function_\">slice<\/span>(addressValueIndex, addressValueIndex + addressLength)<\/span>\n<span class=\"line\">\t\t\t);<\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ 2001:0db8:85a3:0000:0000:8a2e:0370:7334<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> ipv6 = [];<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">for<\/span> (<span class=\"keyword\">let<\/span> i = <span class=\"number\">0<\/span>; i &lt; <span class=\"number\">8<\/span>; i++) {<\/span>\n<span class=\"line\">\t\t\t\tipv6.<span class=\"title function_\">push<\/span>(dataView.<span class=\"title function_\">getUint16<\/span>(i * <span class=\"number\">2<\/span>).<span class=\"title function_\">toString<\/span>(<span class=\"number\">16<\/span>));<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t\taddressValue = ipv6.<span class=\"title function_\">join<\/span>(<span class=\"string\">':'<\/span>);<\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ seems no need add [] for ipv6<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">break<\/span>;<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">default<\/span>:<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"attr\">hasError<\/span>: <span class=\"literal\">true<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"attr\">message<\/span>: <span class=\"string\">`invild  addressType is <span class=\"subst\">${addressType}<\/span>`<\/span>,<\/span>\n<span class=\"line\">\t\t\t};<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (!addressValue) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">hasError<\/span>: <span class=\"literal\">true<\/span>,<\/span>\n<span class=\"line\">\t\t\t<span class=\"attr\">message<\/span>: <span class=\"string\">`addressValue is empty, addressType is <span class=\"subst\">${addressType}<\/span>`<\/span>,<\/span>\n<span class=\"line\">\t\t};<\/span>\n<span class=\"line\">\t}<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">hasError<\/span>: <span class=\"literal\">false<\/span>,<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">addressRemote<\/span>: addressValue,<\/span>\n<span class=\"line\">\t\taddressType,<\/span>\n<span class=\"line\">\t\tportRemote,<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">rawDataIndex<\/span>: addressValueIndex + addressLength,<\/span>\n<span class=\"line\">\t\t<span class=\"attr\">vlessVersion<\/span>: version,<\/span>\n<span class=\"line\">\t\tisUDP,<\/span>\n<span class=\"line\">\t};<\/span>\n<span class=\"line\">}<\/span>\n\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Converts a remote socket to a WebSocket connection.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").Socket<\/span>} remoteSocket The remote socket to convert.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").WebSocket<\/span>} webSocket The WebSocket to connect to.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">ArrayBuffer | null<\/span>} vlessResponseHeader The VLESS response header.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">(() =&gt; Promise&lt;void&gt;) | null<\/span>} retry The function to retry the connection if it fails.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">(info: string) =&gt; void<\/span>} log The logging function.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">Promise&lt;void&gt;<\/span>} A Promise that resolves when the conversion is complete.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">remoteSocketToWS<\/span>(<span class=\"params\">remoteSocket, webSocket, vlessResponseHeader, retry, log<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ remote--&gt; ws<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> remoteChunkCount = <span class=\"number\">0<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> chunks = [];<\/span>\n<span class=\"line\">\t<span class=\"comment\">\/** <span class=\"doctag\">@type<\/span> {<span class=\"type\">ArrayBuffer | null<\/span>} *\/<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> vlessHeader = vlessResponseHeader;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> hasIncomingData = <span class=\"literal\">false<\/span>; <span class=\"comment\">\/\/ check if remoteSocket has incoming data<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">await<\/span> remoteSocket.<span class=\"property\">readable<\/span><\/span>\n<span class=\"line\">\t\t.<span class=\"title function_\">pipeTo<\/span>(<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">new<\/span> <span class=\"title class_\">WritableStream<\/span>({<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">start<\/span>() {<\/span>\n<span class=\"line\">\t\t\t\t},<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t\t\t * <\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t\t\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">Uint8Array<\/span>} chunk <\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t\t\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">*<\/span>} controller <\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t\t\t *\/<\/span><\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">async<\/span> <span class=\"title function_\">write<\/span>(<span class=\"params\">chunk, controller<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t\thasIncomingData = <span class=\"literal\">true<\/span>;<\/span>\n<span class=\"line\">\t\t\t\t\tremoteChunkCount++;<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"keyword\">if<\/span> (webSocket.<span class=\"property\">readyState<\/span> !== <span class=\"variable constant_\">WS_READY_STATE_OPEN<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t\t\tcontroller.<span class=\"title function_\">error<\/span>(<\/span>\n<span class=\"line\">\t\t\t\t\t\t\t<span class=\"string\">'webSocket.readyState is not open, maybe close'<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t);<\/span>\n<span class=\"line\">\t\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"keyword\">if<\/span> (vlessHeader) {<\/span>\n<span class=\"line\">\t\t\t\t\t\twebSocket.<span class=\"title function_\">send<\/span>(<span class=\"keyword\">await<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Blob<\/span>([vlessHeader, chunk]).<span class=\"title function_\">arrayBuffer<\/span>());<\/span>\n<span class=\"line\">\t\t\t\t\t\tvlessHeader = <span class=\"literal\">null<\/span>;<\/span>\n<span class=\"line\">\t\t\t\t\t} <span class=\"keyword\">else<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ console.log(`remoteSocketToWS send chunk ${chunk.byteLength}`);<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ seems no need rate limit this, CF seems fix this??..<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ if (remoteChunkCount &gt; 20000) {<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ \t\/\/ cf one package is 4096 byte(4kb),  4096 * 20000 = 80M<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ \tawait delay(1);<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"comment\">\/\/ }<\/span><\/span>\n<span class=\"line\">\t\t\t\t\t\twebSocket.<span class=\"title function_\">send<\/span>(chunk);<\/span>\n<span class=\"line\">\t\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t\t},<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">close<\/span>() {<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`remoteConnection!.readable is close with hasIncomingData is <span class=\"subst\">${hasIncomingData}<\/span>`<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"comment\">\/\/ safeCloseWebSocket(webSocket); \/\/ no need server close websocket frist for some case will casue HTTP ERR_CONTENT_LENGTH_MISMATCH issue, client will send close event anyway.<\/span><\/span>\n<span class=\"line\">\t\t\t\t},<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">abort<\/span>(<span class=\"params\">reason<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">error<\/span>(<span class=\"string\">`remoteConnection!.readable abort`<\/span>, reason);<\/span>\n<span class=\"line\">\t\t\t\t},<\/span>\n<span class=\"line\">\t\t\t})<\/span>\n<span class=\"line\">\t\t)<\/span>\n<span class=\"line\">\t\t.<span class=\"title function_\">catch<\/span>(<span class=\"function\">(<span class=\"params\">error<\/span>) =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">error<\/span>(<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"string\">`remoteSocketToWS has exception `<\/span>,<\/span>\n<span class=\"line\">\t\t\t\terror.<span class=\"property\">stack<\/span> || error<\/span>\n<span class=\"line\">\t\t\t);<\/span>\n<span class=\"line\">\t\t\t<span class=\"title function_\">safeCloseWebSocket<\/span>(webSocket);<\/span>\n<span class=\"line\">\t\t});<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ seems is cf connect socket have error,<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ 1. Socket.closed will have error<\/span><\/span>\n<span class=\"line\">\t<span class=\"comment\">\/\/ 2. Socket.readable will be close without any data coming<\/span><\/span>\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (hasIncomingData === <span class=\"literal\">false<\/span> &amp;&amp; retry) {<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`retry`<\/span>)<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">retry<\/span>();<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Decodes a base64 string into an ArrayBuffer.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} base64Str The base64 string to decode.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">{earlyData: ArrayBuffer|null, error: Error|null<\/span>}} An object containing the decoded ArrayBuffer or null if there was an error, and any error that occurred during decoding or null if there was no error.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">base64ToArrayBuffer<\/span>(<span class=\"params\">base64Str<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (!base64Str) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> { <span class=\"attr\">earlyData<\/span>: <span class=\"literal\">null<\/span>, <span class=\"attr\">error<\/span>: <span class=\"literal\">null<\/span> };<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">\t<span class=\"keyword\">try<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"comment\">\/\/ go use modified Base64 for URL rfc4648 which js atob not support<\/span><\/span>\n<span class=\"line\">\t\tbase64Str = base64Str.<span class=\"title function_\">replace<\/span>(<span class=\"regexp\">\/-\/g<\/span>, <span class=\"string\">'+'<\/span>).<span class=\"title function_\">replace<\/span>(<span class=\"regexp\">\/_\/g<\/span>, <span class=\"string\">'\/'<\/span>);<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">const<\/span> decode = <span class=\"title function_\">atob<\/span>(base64Str);<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">const<\/span> arryBuffer = <span class=\"title class_\">Uint8Array<\/span>.<span class=\"title function_\">from<\/span>(decode, <span class=\"function\">(<span class=\"params\">c<\/span>) =&gt;<\/span> c.<span class=\"title function_\">charCodeAt<\/span>(<span class=\"number\">0<\/span>));<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> { <span class=\"attr\">earlyData<\/span>: arryBuffer.<span class=\"property\">buffer<\/span>, <span class=\"attr\">error<\/span>: <span class=\"literal\">null<\/span> };<\/span>\n<span class=\"line\">\t} <span class=\"keyword\">catch<\/span> (error) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">return<\/span> { <span class=\"attr\">earlyData<\/span>: <span class=\"literal\">null<\/span>, error };<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Checks if a given string is a valid UUID.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Note: This is not a real UUID validation.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} uuid The string to validate as a UUID.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">boolean<\/span>} True if the string is a valid UUID, false otherwise.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">isValidUUID<\/span>(<span class=\"params\">uuid<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> uuidRegex = <span class=\"regexp\">\/^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$\/i<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> uuidRegex.<span class=\"title function_\">test<\/span>(uuid);<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"keyword\">const<\/span> <span class=\"variable constant_\">WS_READY_STATE_OPEN<\/span> = <span class=\"number\">1<\/span>;<\/span>\n<span class=\"line\"><span class=\"keyword\">const<\/span> <span class=\"variable constant_\">WS_READY_STATE_CLOSING<\/span> = <span class=\"number\">2<\/span>;<\/span>\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Closes a WebSocket connection safely without throwing exceptions.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").WebSocket<\/span>} socket The WebSocket connection to close.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">safeCloseWebSocket<\/span>(<span class=\"params\">socket<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">try<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">if<\/span> (socket.<span class=\"property\">readyState<\/span> === <span class=\"variable constant_\">WS_READY_STATE_OPEN<\/span> || socket.<span class=\"property\">readyState<\/span> === <span class=\"variable constant_\">WS_READY_STATE_CLOSING<\/span>) {<\/span>\n<span class=\"line\">\t\t\tsocket.<span class=\"title function_\">close<\/span>();<\/span>\n<span class=\"line\">\t\t}<\/span>\n<span class=\"line\">\t} <span class=\"keyword\">catch<\/span> (error) {<\/span>\n<span class=\"line\">\t\t<span class=\"variable language_\">console<\/span>.<span class=\"title function_\">error<\/span>(<span class=\"string\">'safeCloseWebSocket error'<\/span>, error);<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"keyword\">const<\/span> byteToHex = [];<\/span>\n\n<span class=\"line\"><span class=\"keyword\">for<\/span> (<span class=\"keyword\">let<\/span> i = <span class=\"number\">0<\/span>; i &lt; <span class=\"number\">256<\/span>; ++i) {<\/span>\n<span class=\"line\">\tbyteToHex.<span class=\"title function_\">push<\/span>((i + <span class=\"number\">256<\/span>).<span class=\"title function_\">toString<\/span>(<span class=\"number\">16<\/span>).<span class=\"title function_\">slice<\/span>(<span class=\"number\">1<\/span>));<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">unsafeStringify<\/span>(<span class=\"params\">arr, offset = <span class=\"number\">0<\/span><\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> (byteToHex[arr[offset + <span class=\"number\">0<\/span>]] + byteToHex[arr[offset + <span class=\"number\">1<\/span>]] + byteToHex[arr[offset + <span class=\"number\">2<\/span>]] + byteToHex[arr[offset + <span class=\"number\">3<\/span>]] + <span class=\"string\">\"-\"<\/span> + byteToHex[arr[offset + <span class=\"number\">4<\/span>]] + byteToHex[arr[offset + <span class=\"number\">5<\/span>]] + <span class=\"string\">\"-\"<\/span> + byteToHex[arr[offset + <span class=\"number\">6<\/span>]] + byteToHex[arr[offset + <span class=\"number\">7<\/span>]] + <span class=\"string\">\"-\"<\/span> + byteToHex[arr[offset + <span class=\"number\">8<\/span>]] + byteToHex[arr[offset + <span class=\"number\">9<\/span>]] + <span class=\"string\">\"-\"<\/span> + byteToHex[arr[offset + <span class=\"number\">10<\/span>]] + byteToHex[arr[offset + <span class=\"number\">11<\/span>]] + byteToHex[arr[offset + <span class=\"number\">12<\/span>]] + byteToHex[arr[offset + <span class=\"number\">13<\/span>]] + byteToHex[arr[offset + <span class=\"number\">14<\/span>]] + byteToHex[arr[offset + <span class=\"number\">15<\/span>]]).<span class=\"title function_\">toLowerCase<\/span>();<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">stringify<\/span>(<span class=\"params\">arr, offset = <span class=\"number\">0<\/span><\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> uuid = <span class=\"title function_\">unsafeStringify<\/span>(arr, offset);<\/span>\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (!<span class=\"title function_\">isValidUUID<\/span>(uuid)) {<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">throw<\/span> <span class=\"title class_\">TypeError<\/span>(<span class=\"string\">\"Stringified UUID is invalid\"<\/span>);<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> uuid;<\/span>\n<span class=\"line\">}<\/span>\n\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * Handles outbound UDP traffic by transforming the data into DNS queries and sending them over a WebSocket connection.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">import(\"@cloudflare\/workers-types\").WebSocket<\/span>} webSocket The WebSocket connection to send the DNS queries over.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">ArrayBuffer<\/span>} vlessResponseHeader The VLESS response header.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">(string) =&gt; void<\/span>} log The logging function.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">{write: (chunk: Uint8Array) =&gt; void<\/span>}} An object with a write method that accepts a Uint8Array chunk to write to the transform stream.<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">async<\/span> <span class=\"keyword\">function<\/span> <span class=\"title function_\">handleUDPOutBound<\/span>(<span class=\"params\">webSocket, vlessResponseHeader, log<\/span>) {<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">let<\/span> isVlessHeaderSent = <span class=\"literal\">false<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> transformStream = <span class=\"keyword\">new<\/span> <span class=\"title class_\">TransformStream<\/span>({<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">start<\/span>(<span class=\"params\">controller<\/span>) {<\/span>\n\n<span class=\"line\">\t\t},<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">transform<\/span>(<span class=\"params\">chunk, controller<\/span>) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ udp message 2 byte is the the length of udp data<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ <span class=\"doctag\">TODO:<\/span> this should have bug, beacsue maybe udp chunk can be in two websocket message<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">for<\/span> (<span class=\"keyword\">let<\/span> index = <span class=\"number\">0<\/span>; index &lt; chunk.<span class=\"property\">byteLength<\/span>;) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> lengthBuffer = chunk.<span class=\"title function_\">slice<\/span>(index, index + <span class=\"number\">2<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> udpPakcetLength = <span class=\"keyword\">new<\/span> <span class=\"title class_\">DataView<\/span>(lengthBuffer).<span class=\"title function_\">getUint16<\/span>(<span class=\"number\">0<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">const<\/span> udpData = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>(<\/span>\n<span class=\"line\">\t\t\t\t\tchunk.<span class=\"title function_\">slice<\/span>(index + <span class=\"number\">2<\/span>, index + <span class=\"number\">2<\/span> + udpPakcetLength)<\/span>\n<span class=\"line\">\t\t\t\t);<\/span>\n<span class=\"line\">\t\t\t\tindex = index + <span class=\"number\">2<\/span> + udpPakcetLength;<\/span>\n<span class=\"line\">\t\t\t\tcontroller.<span class=\"title function_\">enqueue<\/span>(udpData);<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t},<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">flush<\/span>(<span class=\"params\">controller<\/span>) {<\/span>\n<span class=\"line\">\t\t}<\/span>\n<span class=\"line\">\t});<\/span>\n\n<span class=\"line\">\t<span class=\"comment\">\/\/ only handle dns udp for now<\/span><\/span>\n<span class=\"line\">\ttransformStream.<span class=\"property\">readable<\/span>.<span class=\"title function_\">pipeTo<\/span>(<span class=\"keyword\">new<\/span> <span class=\"title class_\">WritableStream<\/span>({<\/span>\n<span class=\"line\">\t\t<span class=\"keyword\">async<\/span> <span class=\"title function_\">write<\/span>(<span class=\"params\">chunk<\/span>) {<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> resp = <span class=\"keyword\">await<\/span> <span class=\"title function_\">fetch<\/span>(dohURL, <span class=\"comment\">\/\/ dns server url<\/span><\/span>\n<span class=\"line\">\t\t\t\t{<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"attr\">method<\/span>: <span class=\"string\">'POST'<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"attr\">headers<\/span>: {<\/span>\n<span class=\"line\">\t\t\t\t\t\t<span class=\"string\">'content-type'<\/span>: <span class=\"string\">'application\/dns-message'<\/span>,<\/span>\n<span class=\"line\">\t\t\t\t\t},<\/span>\n<span class=\"line\">\t\t\t\t\t<span class=\"attr\">body<\/span>: chunk,<\/span>\n<span class=\"line\">\t\t\t\t})<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> dnsQueryResult = <span class=\"keyword\">await<\/span> resp.<span class=\"title function_\">arrayBuffer<\/span>();<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> udpSize = dnsQueryResult.<span class=\"property\">byteLength<\/span>;<\/span>\n<span class=\"line\">\t\t\t<span class=\"comment\">\/\/ console.log([...new Uint8Array(dnsQueryResult)].map((x) =&gt; x.toString(16)));<\/span><\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">const<\/span> udpSizeBuffer = <span class=\"keyword\">new<\/span> <span class=\"title class_\">Uint8Array<\/span>([(udpSize &gt;&gt; <span class=\"number\">8<\/span>) &amp; <span class=\"number\">0xff<\/span>, udpSize &amp; <span class=\"number\">0xff<\/span>]);<\/span>\n<span class=\"line\">\t\t\t<span class=\"keyword\">if<\/span> (webSocket.<span class=\"property\">readyState<\/span> === <span class=\"variable constant_\">WS_READY_STATE_OPEN<\/span>) {<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">`doh success and dns message length is <span class=\"subst\">${udpSize}<\/span>`<\/span>);<\/span>\n<span class=\"line\">\t\t\t\t<span class=\"keyword\">if<\/span> (isVlessHeaderSent) {<\/span>\n<span class=\"line\">\t\t\t\t\twebSocket.<span class=\"title function_\">send<\/span>(<span class=\"keyword\">await<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Blob<\/span>([udpSizeBuffer, dnsQueryResult]).<span class=\"title function_\">arrayBuffer<\/span>());<\/span>\n<span class=\"line\">\t\t\t\t} <span class=\"keyword\">else<\/span> {<\/span>\n<span class=\"line\">\t\t\t\t\twebSocket.<span class=\"title function_\">send<\/span>(<span class=\"keyword\">await<\/span> <span class=\"keyword\">new<\/span> <span class=\"title class_\">Blob<\/span>([vlessResponseHeader, udpSizeBuffer, dnsQueryResult]).<span class=\"title function_\">arrayBuffer<\/span>());<\/span>\n<span class=\"line\">\t\t\t\t\tisVlessHeaderSent = <span class=\"literal\">true<\/span>;<\/span>\n<span class=\"line\">\t\t\t\t}<\/span>\n<span class=\"line\">\t\t\t}<\/span>\n<span class=\"line\">\t\t}<\/span>\n<span class=\"line\">\t})).<span class=\"title function_\">catch<\/span>(<span class=\"function\">(<span class=\"params\">error<\/span>) =&gt;<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">log<\/span>(<span class=\"string\">'dns udp has error'<\/span> + error)<\/span>\n<span class=\"line\">\t});<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> writer = transformStream.<span class=\"property\">writable<\/span>.<span class=\"title function_\">getWriter<\/span>();<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">return<\/span> {<\/span>\n<span class=\"line\">\t\t<span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t * <\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t * <span class=\"doctag\">@param<\/span> {<span class=\"type\">Uint8Array<\/span>} chunk <\/span><\/span>\n<span class=\"line\"><span class=\"comment\">\t\t *\/<\/span><\/span>\n<span class=\"line\">\t\t<span class=\"title function_\">write<\/span>(<span class=\"params\">chunk<\/span>) {<\/span>\n<span class=\"line\">\t\t\twriter.<span class=\"title function_\">write<\/span>(chunk);<\/span>\n<span class=\"line\">\t\t}<\/span>\n<span class=\"line\">\t};<\/span>\n<span class=\"line\">}<\/span>\n\n<span class=\"line\"><span class=\"comment\">\/**<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string<\/span>} <span class=\"variable\">userID<\/span> - single or comma separated userIDs<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param<\/span> {<span class=\"type\">string | null<\/span>} <span class=\"variable\">hostName<\/span><\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@returns<\/span> {<span class=\"type\">string<\/span>}<\/span><\/span>\n<span class=\"line\"><span class=\"comment\"> *\/<\/span><\/span>\n<span class=\"line\"><span class=\"keyword\">function<\/span> <span class=\"title function_\">getVLESSConfig<\/span>(<span class=\"params\">userID, hostName<\/span>) {<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> wvlessws = <span class=\"string\">`vless:\/\/<span class=\"subst\">${userID}<\/span>@www.visa.com.sg:8880?encryption=none&amp;security=none&amp;type=ws&amp;host=<span class=\"subst\">${hostName}<\/span>&amp;path=%2F%3Fed%3D2048#<span class=\"subst\">${hostName}<\/span>`<\/span>;<\/span>\n<span class=\"line\">\t<span class=\"keyword\">const<\/span> pvlesswstls = <span class=\"string\">`vless:\/\/<span class=\"subst\">${userID}<\/span>@www.visa.com.sg:8443?encryption=none&amp;security=tls&amp;type=ws&amp;host=<span class=\"subst\">${hostName}<\/span>&amp;sni=<span class=\"subst\">${hostName}<\/span>&amp;fp=random&amp;path=%2F%3Fed%3D2048#<span class=\"subst\">${hostName}<\/span>`<\/span>;<\/span>\n\n<span class=\"line\">\t<span class=\"keyword\">if<\/span> (hostName.<span class=\"title function_\">includes<\/span>(<span class=\"string\">'pages.dev'<\/span>)) {<\/span>\n<span class=\"line\">\t  <span class=\"keyword\">return<\/span> <span class=\"string\">`<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;==========================\u914d\u7f6e\u8be6\u89e3==============================&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;CF-pages-vless+ws+tls\u8282\u70b9\uff0c\u5206\u4eab\u94fe\u63a5\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;<span class=\"subst\">${pvlesswstls}<\/span>&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u6ce8\u610f\uff1a\u5982\u679c <span class=\"subst\">${hostName}<\/span> \u5728\u672c\u5730\u7f51\u7edc\u6253\u4e0d\u5f00\uff08\u4e2d\u56fd\u79fb\u52a8\u7528\u6237\u6ce8\u610f\uff09&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u9009\u9879\u7684\u4f2a\u88c5\u57df\u540d(host)\u5fc5\u987b\u6539\u4e3a\u4f60\u5728CF\u89e3\u6790\u5b8c\u6210\u7684\u81ea\u5b9a\u4e49\u57df\u540d&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5fc5\u8981\u6587\u660e\u53c2\u6570\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5730\u5740(address)\uff1a\u81ea\u5b9a\u4e49\u7684\u57df\u540d \u6216\u8005 \u4f18\u9009\u57df\u540d \u6216\u8005 \u4f18\u9009IP\uff08\u53cd\u4ee3IP\u5fc5\u987b\u4e0e\u53cd\u4ee3\u7aef\u53e3\u5bf9\u5e94\uff09&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7aef\u53e3(port)\uff1a6\u4e2ahttps\u7aef\u53e3\u53ef\u4efb\u610f\u9009\u62e9(443\u30018443\u30012053\u30012083\u30012087\u30012096)&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7528\u6237ID(uuid)\uff1a<span class=\"subst\">${userID}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f20\u8f93\u534f\u8bae(network)\uff1aws \u6216\u8005 websocket&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f2a\u88c5\u57df\u540d(host)\uff1a<span class=\"subst\">${hostName}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u8def\u5f84(path)\uff1a\/?ed=2048&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f20\u8f93\u5b89\u5168(TLS)\uff1a\u5f00\u542f&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u8df3\u8fc7\u8bc1\u4e66\u9a8c\u8bc1(allowlnsecure)\uff1afalse&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  `<\/span>;<\/span>\n\n<span class=\"line\">\t} <span class=\"keyword\">else<\/span> <span class=\"keyword\">if<\/span> (hostName.<span class=\"title function_\">includes<\/span>(<span class=\"string\">'workers.dev'<\/span>))  {<\/span>\n<span class=\"line\">\t  <span class=\"keyword\">return<\/span> <span class=\"string\">`<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;==========================\u914d\u7f6e\u8be6\u89e3==============================&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4e00\u3001CF-workers-vless+ws\u8282\u70b9\uff0c\u5206\u4eab\u94fe\u63a5\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;<span class=\"subst\">${wvlessws}<\/span>&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u6ce8\u610f\uff1a\u5f53\u524d\u8282\u70b9\u65e0\u9700\u4f7f\u7528CF\u89e3\u6790\u5b8c\u6210\u7684\u57df\u540d\uff0c\u5ba2\u6237\u7aef\u9009\u9879\u7684TLS\u9009\u9879\u5fc5\u987b\u5173\u95ed&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5fc5\u8981\u6587\u660e\u53c2\u6570\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5730\u5740(address)\uff1a\u81ea\u5b9a\u4e49\u7684\u57df\u540d \u6216\u8005 \u4f18\u9009\u57df\u540d \u6216\u8005 \u4f18\u9009IP\uff08\u53cd\u4ee3IP\u5fc5\u987b\u4e0e\u53cd\u4ee3\u7aef\u53e3\u5bf9\u5e94\uff09&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7aef\u53e3(port)\uff1a7\u4e2ahttp\u7aef\u53e3\u53ef\u4efb\u610f\u9009\u62e9(80\u30018080\u30018880\u30012052\u30012082\u30012086\u30012095)&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7528\u6237ID(uuid)\uff1a<span class=\"subst\">${userID}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f20\u8f93\u534f\u8bae(network)\uff1aws \u6216\u8005 websocket&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f2a\u88c5\u57df\u540d(host)\uff1a<span class=\"subst\">${hostName}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u8def\u5f84(path)\uff1a\/?ed=2048&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4e8c\u3001CF-workers-vless+ws+tls\u8282\u70b9\u6ce8\u610f\uff1a\u8bf7\u5728\u6d4f\u89c8\u5668\u5730\u5740\u680f\u8f93\u5165\uff1a\u4f60\u8bbe\u7f6e\u7684\u81ea\u5b9a\u4e49\u57df\u540d\/\u4f60\u8bbe\u7f6e\u7684UUID&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u9632\u6b62\u5c0f\u767d\u8fc7\u591a\u7684\u64cd\u4f5c\u5931\u8bef\uff0c\u5fc5\u987b\u8bbe\u7f6e\u81ea\u5b9a\u4e49\u57df\u540d\u540e\u624d\u80fd\u4f7f\u7528Workers\u65b9\u5f0f\u7684TLS\u6a21\u5f0f\uff0c\u5426\u5219\uff0c\u5efa\u8bae\u53ea\u4f7f\u7528vless+ws\u8282\u70b9\u5373\u53ef&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u63d0\u793a\uff1a\u4f7f\u7528pages\u65b9\u5f0f\u90e8\u7f72\uff0c\u8054\u901a\u3001\u7535\u4fe1\u7528\u6237\u5927\u6982\u7387\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528TLS\u6a21\u5f0f\uff0c\u65e0\u9700\u8bbe\u7f6e\u81ea\u5b9a\u4e49\u57df\u540d&lt;\/p&gt;<\/span><\/span>\n\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  `<\/span>;<\/span>\n<span class=\"line\">\t} <span class=\"keyword\">else<\/span> {<\/span>\n<span class=\"line\">\t  <span class=\"keyword\">return<\/span> <span class=\"string\">`<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;==========================\u914d\u7f6e\u8be6\u89e3==============================&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;=====\u4f7f\u7528\u81ea\u5b9a\u4e49\u57df\u540d\u67e5\u770b\u914d\u7f6e\uff0c\u8bf7\u786e\u8ba4\u4f7f\u7528\u7684\u662fworkers\u8fd8\u662fpages=====&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4e00\u3001CF-workers-vless+ws\u8282\u70b9\uff0c\u5206\u4eab\u94fe\u63a5\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;<span class=\"subst\">${wvlessws}<\/span>&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u6ce8\u610f\uff1a\u5f53\u524d\u8282\u70b9\u65e0\u9700\u4f7f\u7528CF\u89e3\u6790\u5b8c\u6210\u7684\u57df\u540d\uff0c\u5ba2\u6237\u7aef\u9009\u9879\u7684TLS\u9009\u9879\u5fc5\u987b\u5173\u95ed&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5fc5\u8981\u6587\u660e\u53c2\u6570\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5730\u5740(address)\uff1a\u81ea\u5b9a\u4e49\u7684\u57df\u540d \u6216\u8005 \u4f18\u9009\u57df\u540d \u6216\u8005 \u4f18\u9009IP\uff08\u53cd\u4ee3IP\u5fc5\u987b\u4e0e\u53cd\u4ee3\u7aef\u53e3\u5bf9\u5e94\uff09&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7aef\u53e3(port)\uff1a7\u4e2ahttp\u7aef\u53e3\u53ef\u4efb\u610f\u9009\u62e9(80\u30018080\u30018880\u30012052\u30012082\u30012086\u30012095)&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7528\u6237ID(uuid)\uff1a<span class=\"subst\">${userID}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f20\u8f93\u534f\u8bae(network)\uff1aws \u6216\u8005 websocket&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f2a\u88c5\u57df\u540d(host)\uff1a<span class=\"subst\">${hostName}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u8def\u5f84(path)\uff1a\/?ed=2048&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4e8c\u3001CF-workers-vless+ws+tls \u6216\u8005 CF-pages-vless+ws+tls\u8282\u70b9\uff0c\u5206\u4eab\u94fe\u63a5\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;<span class=\"subst\">${pvlesswstls}<\/span>&lt;\/p&gt;<\/span><\/span>\n\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u6ce8\u610f\uff1a\u5ba2\u6237\u7aef\u9009\u9879\u7684\u4f2a\u88c5\u57df\u540d(host)\u5fc5\u987b\u6539\u4e3a\u4f60\u5728CF\u89e3\u6790\u5b8c\u6210\u7684\u81ea\u5b9a\u4e49\u57df\u540d&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;---------------------------------------------------------------&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5fc5\u8981\u6587\u660e\u53c2\u6570\u5982\u4e0b\uff1a&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u5ba2\u6237\u7aef\u5730\u5740(address)\uff1a\u81ea\u5b9a\u4e49\u7684\u57df\u540d \u6216\u8005 \u4f18\u9009\u57df\u540d \u6216\u8005 \u4f18\u9009IP\uff08\u53cd\u4ee3IP\u5fc5\u987b\u4e0e\u53cd\u4ee3\u7aef\u53e3\u5bf9\u5e94\uff09&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7aef\u53e3(port)\uff1a6\u4e2ahttps\u7aef\u53e3\u53ef\u4efb\u610f\u9009\u62e9(443\u30018443\u30012053\u30012083\u30012087\u30012096)&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u7528\u6237ID(uuid)\uff1a<span class=\"subst\">${userID}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f20\u8f93\u534f\u8bae(network)\uff1aws \u6216\u8005 websocket&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f2a\u88c5\u57df\u540d(host)\uff1a<span class=\"subst\">${hostName}<\/span>&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u8def\u5f84(path)\uff1a\/?ed=2048&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u4f20\u8f93\u5b89\u5168(TLS)\uff1a\u5f00\u542f&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;\u8df3\u8fc7\u8bc1\u4e66\u9a8c\u8bc1(allowlnsecure)\uff1afalse&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  &lt;p&gt;################################################################&lt;\/p&gt;<\/span><\/span>\n<span class=\"line\"><span class=\"string\">  `<\/span>;<\/span>\n<span class=\"line\">\t}<\/span>\n<span class=\"line\">  }<\/span>\n<span class=\"line\"><span class=\"keyword\">const<\/span> cn_hostnames = [<\/span>\n<span class=\"line\"><span class=\"string\">'www.wto.org'<\/span><\/span>\n<span class=\"line\">];<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<\/article>\n<div class=\"post-copyright\">\n<div class=\"post-copyright__author\"><span class=\"post-copyright-meta\">\u6587\u7ae0\u4f5c\u8005:\u00a0<\/span><span class=\"post-copyright-info\"><a rel=\"nofollow\" href=\"https:\/\/polar-bear.eu.org\/\">Ziyourufeng<\/a><\/span><\/div>\n<div class=\"post-copyright__type\"><span class=\"post-copyright-meta\">\u6587\u7ae0\u94fe\u63a5:\u00a0<\/span><span class=\"post-copyright-info\"><a rel=\"nofollow\" href=\"https:\/\/polar-bear.eu.org\/2024\/03\/30\/cf-workers-vless-mian-fei-jie-dian-da-jian\/\">https:\/\/polar-bear.eu.org\/2024\/03\/30\/cf-workers-vless-mian-fei-jie-dian-da-jian\/<\/a><\/span><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u90e8\u7f72 \u8fdb\u5165cloudflare\u521b\u5efaworkers \u7136\u540e\u8fdb\u5165\u4f60\u7684\u4ee3\u7801\u7f16\u8f91\u9875\u9762\uff0c\u7c98\u8d34\u4e0b\u65b9\u4ee3\u7801\u3002 \u9700\u8981\u6539\u52a8\u4ee5\u4e0b\u5185\u5bb9 userID \u6b64\u4e3avless\u9274\u5b9a\u7528\u6237\u7684id\uff0c\u9700\u81ea\u884c\u751f\u6210\u5e76\u66ff\u6362\u3002 proxyIPs \u4ee3\u7406\u670d\u52a1\u5668\u7684\u57df\u540d\u6216IP\u5730\u5740,\u5373\u5229\u7528\u54ea\u4e9b\u53ef\u4ee5\u7684cl&#8230;<\/p>\n","protected":false},"author":1,"featured_media":6419,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[136],"tags":[],"topic":[],"class_list":["post-6411","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-136"],"_links":{"self":[{"href":"http:\/\/puo.cn\/index.php?rest_route=\/wp\/v2\/posts\/6411","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/puo.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/puo.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/puo.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/puo.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6411"}],"version-history":[{"count":1,"href":"http:\/\/puo.cn\/index.php?rest_route=\/wp\/v2\/posts\/6411\/revisions"}],"predecessor-version":[{"id":643983,"href":"http:\/\/puo.cn\/index.php?rest_route=\/wp\/v2\/posts\/6411\/revisions\/643983"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/puo.cn\/index.php?rest_route=\/"}],"wp:attachment":[{"href":"http:\/\/puo.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/puo.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6411"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/puo.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6411"},{"taxonomy":"topic","embeddable":true,"href":"http:\/\/puo.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftopic&post=6411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}