location/gateway/port selection in v5

Hey, I'm currently implementing/integrating v5 (bitmaks-core/menshen) into the desktop client (#758 (closed)).

If we start the desktop client, we see a list of locations and the quality of each location. Currently, this is hardcoded in my branch:

available locations

locationLabels := make(map[string][]string)
locationLabels["Paris"] = []string{"Paris", "Fr"}
locationLabels["Seattle"] = []string{"Seattle", "US"}
return locationLabels

quality

cm := make(map[string]float64)
cm["Paris"] = 0.84
cm["Seattle"] = 0.3
return cm

best location

return "Paris"

Now I want to fill this with logic. Therefore, we need to agree on how to implement this. This is my proposal on how to implement this:

  1. menshen does not give us a list of availabale locations
    • we only get a list of gateways
    • each gateway has a field: location
    • PROPOSAL: we keep it as it is. No need for an /locations endpoint

UPDATE:

  • there is a /Service endpoint in menshen. I think it's only meant for v3-backwards compatiblity
  • this endpoint also returns locations
  • bitmask-core has Locations() that gives us the locations, but we have to call FetchService() before (not very intuitive)
  1. quality of a location
    • definition of quality: latency + load
    • latency: calculate the latency to each gateway (on the client side, already implemented in bitmask-core)
      • edge case: what if (only) icmp is blocked => ignore this host vs enqueue at the end to the list of gateways per location
    • load: needs to be differentiated
      • We have a load per gateway and a load for each openvpn process of a gateway
        • total load of the gateway: there is a load field in the api response for every gateway => just use this value
        • load of multiple openvpn processes per gateway: handled by the ports returned to the api client (prefered port or ordered list of ports)
    • calculation proposal
      • for each location: check latency for all gateways and calculate average
      • ignore load of single gateways (easy to implment, load will be considered later)

If the user connects/clicks on a location

  • connect to 2? gateways of the selected location (check QUESTIONS (2) below)
  • the latency of gateways in a single location should not differ much => ignore
  • connection order of gateways: by total load of the gateway
  • honor load of openvpn processes per host
  • prefer udp over tcp

So for example menshen gives us the following information:

paris01 lat=0.5 load=1 port1=80-tcp-0.7 port2=443-tcp-0.8
paris02 lat=0.3 load=2 ...
paris03 lat=0.1 load=1.5 ...
paris04 lat=0.8 load=0.4 port1=53-udp-0.3 port2=1194-udp-0.5 port3=80-tcp-0.7

connection order

  1. ignore latency of gateway
  2. order by total gateway load: paris04, paris01 paris03, paris02 (but only use the first 2?)
  3. for each host: order ports (honor load, then udp over tcp - that's conflicting, see QUESTIONS below)

Start openvpn with the following arguments

--remote paris04 53 udp4
--remote paris04 1194 udp4
--remote paris04 80 tcp4
--remote paris01 80 tcp4
--remote paris01 443 tcp4

QUESTIONS

  1. Definition of load (only relevant for implementation in menshen)

    • load of a gateway:
      • just the system load given by uptime?
      • Or current network bandwith used?
      • Or bandwith utilization?
    • load of a gateway process:
      • connected users?
      • network traffic per process?
      • How to get this information?
  2. How many gateways per location to connect with

    • what if we can't connect to 2 gateways of a single location
      • probably the whole location (all gateways of this country) is blocked
    • tell the user OpenVPN failed and they should use a different location?
    • to calculate the latency, we ping the host => we know if we can reach them
      • what if only icmp is blocked?
  3. If we have a gateway with 6 listening openvpn ports

    • how many ports do we try to connect (regarding --remote argument)
    • when do we want to switch to the next gateway
    • what's likely to fail (or blocked): OpenVPN process or gateway
    • what if we use the first two, but they are only UDP and UDP is blocked
  4. We want poeple to use UDP

    • this means: UDP openvpn processes have a higher load
    • if we order ports just by load of openvpn processes => menshen will people tell to use the TCP port because the load is lower
  5. UPDATE: In bitmask-core, there is code about Geolocation

  • looks like this: get location by third party api
  • ask menshen for gateways in this area

It would be nice if people could think about this and then let's have a call to decide. @kali @cyberta @jkito @sgk

Edited by Pea Nut