@@ -643,3 +643,97 @@ func enrichResultsWithGeoIP(results []configResult, settings GeoSettings) []conf
643643
644644 return results
645645}
646+
647+ // ── Cloudflare port expansion ────────────────────────────────────────────────
648+
649+ var cfPorts = []string {
650+ "443" , "8443" , "2053" , "2083" , "2087" , "2096" ,
651+ "80" , "8080" , "8880" , "2052" , "2082" , "2086" , "2095" ,
652+ }
653+
654+ func expandCloudflarePorts (lines []string ) []string {
655+ seen := make (map [string ]bool , len (lines ))
656+ var result []string
657+
658+ for _ , line := range lines {
659+ proto := detectProto (line )
660+ if proto != "vless" && proto != "trojan" {
661+ if ! seen [line ] {
662+ seen [line ] = true
663+ result = append (result , line )
664+ }
665+ continue
666+ }
667+ if ! isWSTransport (line , proto ) {
668+ if ! seen [line ] {
669+ seen [line ] = true
670+ result = append (result , line )
671+ }
672+ continue
673+ }
674+
675+ host := extractServerHost (line , proto )
676+ if host == "" {
677+ if ! seen [line ] {
678+ seen [line ] = true
679+ result = append (result , line )
680+ }
681+ continue
682+ }
683+
684+ ip := resolveHost (host )
685+ if ip == "" || ! isCloudflareIP (ip ) {
686+ if ! seen [line ] {
687+ seen [line ] = true
688+ result = append (result , line )
689+ }
690+ continue
691+ }
692+
693+ // Cloudflare WS config — expand to all ports
694+ for _ , port := range cfPorts {
695+ expanded := replacePort (line , port )
696+ if expanded != "" && ! seen [expanded ] {
697+ seen [expanded ] = true
698+ result = append (result , expanded )
699+ }
700+ }
701+ }
702+
703+ expanded := len (result ) - len (lines )
704+ if expanded > 0 {
705+ fmt .Printf (" Cloudflare: expanded %d configs to %d port variants\n " , len (lines ), len (result ))
706+ }
707+ return result
708+ }
709+
710+ func replacePort (line , newPort string ) string {
711+ hashIdx := strings .LastIndex (line , "#" )
712+ suffix := ""
713+ if hashIdx != - 1 {
714+ suffix = line [hashIdx :]
715+ line = line [:hashIdx ]
716+ }
717+
718+ qIdx := strings .Index (line , "?" )
719+ var base , query string
720+ if qIdx != - 1 {
721+ base = line [:qIdx ]
722+ query = line [qIdx :]
723+ } else {
724+ base = line
725+ }
726+
727+ atIdx := strings .LastIndex (base , "@" )
728+ if atIdx == - 1 {
729+ return ""
730+ }
731+ afterAt := base [atIdx + 1 :]
732+ colonIdx := strings .LastIndex (afterAt , ":" )
733+ if colonIdx == - 1 {
734+ return ""
735+ }
736+ host := afterAt [:colonIdx ]
737+ rewritten := base [:atIdx + 1 ] + host + ":" + newPort + query + suffix
738+ return rewritten
739+ }
0 commit comments