@@ -31,6 +31,7 @@ type Server struct {
3131 Continent string `json:"continent"`
3232 Country string `json:"country"`
3333 Protocols []string `json:"protocols"`
34+ IPv6 bool `json:"ipv6"`
3435 Rules []Rule `json:"rules,omitempty"`
3536 Redirects prometheus.Counter `json:"-"`
3637 LastChange time.Time `json:"lastChange"`
@@ -201,8 +202,12 @@ type ComputedDistance struct {
201202// it computes the distances. If the nearest server is within a threshold (e.g. 50km),
202203// it is selected deterministically; otherwise, a weighted selection is used.
203204// If no local servers exist, it falls back to a weighted selection among all valid servers.
204- func (s ServerList ) Closest (r * Redirector , scheme string , ip net.IP ) (* Server , float64 , error ) {
205+ // If requireIPv6 is true, servers without IPv6 support are filtered out.
206+ func (s ServerList ) Closest (r * Redirector , scheme string , ip net.IP , requireIPv6 bool ) (* Server , float64 , error ) {
205207 cacheKey := scheme + "_" + ip .String ()
208+ if requireIPv6 {
209+ cacheKey += "_v6"
210+ }
206211
207212 if cached , exists := r .serverCache .Get (cacheKey ); exists {
208213 if comp , ok := cached .(ComputedDistance ); ok {
@@ -237,6 +242,12 @@ func (s ServerList) Closest(r *Redirector, scheme string, ip net.IP) (*Server, f
237242 if ! server .Available || ! lo .Contains (server .Protocols , scheme ) {
238243 return false
239244 }
245+
246+ // If user is on IPv6, filter out servers that don't support IPv6
247+ if requireIPv6 && ! server .IPv6 {
248+ log .WithField ("host" , server .Host ).Debug ("Skipping server due to no IPv6 support" )
249+ return false
250+ }
240251 if len (server .Rules ) > 0 && ! server .checkRules (ruleInput ) {
241252 log .WithField ("host" , server .Host ).Debug ("Skipping server due to rules" )
242253 return false
0 commit comments