On 2015-08-11 17:08, Arne Schwabe wrote:

Am 11.08.15 um 16:42 schrieb Gergely Czuczy:
Hello,

I would like to ask some help, I'm looking at the OpenVPN source tree
from GitHub as I would like to see how much effort would it be me to add
SRV record support, as it has increasing demand these days (and really
makes sense, especially for enterprises).

So, the question is, what would be the best place to hook up the support
for SRV records?
SRV record mechanism/requirements are the following:
   - It's protocol-specific, so at lookup time it has to be known whether
it's for UDP or TCP
If proto were optional that would fit OpenVPN better. But SRV records
seem not support that.
As Gert already pointed out, this is not that hard. To his comments I would like to add mine. Personally I think that it's fairly rare when someone has the same OpenVPN service on both UDP and TCP active (AFAIK this kind of configuration is not even supported by the config). Therefore the mechanism can check the existence of both kind of SRV records, for-just-in-case define a priority order for the protocols,
then handle the found SRV record by that.

   - The SRV records supply the service port, so in this case it's not
taken from the configuration file.
   - Basically for a service it's one or more DNS records in the
following format:
    _service._proto.name. TTL class SRV priority weight port target.
    I guess _service should be _openvpn, _proto is either _tcp or _udp.
port is obvious, and target is the target host to connect to using the
previously specified port.
    If there are multiple records, then priority makes sense, first the
hosts with the lowest values have to be tried, then rest increasingly
    If there are multiple hosts with the same priority then weight kicks
in, a host to be chosen is determined by the weight factors. Attempts to
a different priority can be made after all hosts from this priority are
exhausted.
Multiple records are difficult. At the moment we have a list of
connection entries in the config which may expand into multiple
addresses (from getaddrinfo). The question if we do a dns lookup at the
start for SRV enabled connection entries and mutate these entries into
multiple entries or this should be done as part of the normal resolve
process for each entry, introducing the concept of subconnections or
something like this.

Doing a one reordering after priority and doing a weighted randomizing
between connections with same priority should not be a problem.
Personally I'm thinking about having the SRV record mechanism up a level of the normal connection lookup mechanism. The current way you've describe makes total sense, and that kind of functionality is still totally valid for every address produced by the SRV mechanism.

So I'm thinking along the lines a good place to hook it would be where the current connection mechanism is called, and replace that call with the SRV lookups mechanism. So, instead of just connecting to the address in the configuration file, check for SRV records, if they exist then do the SRV logic, if there's no SRV record found, then proceed as it's currently being done.

With pseudo-code (without actually quoting the source, so naming convention doesn't match):
Instead of:
  ovpn_connect(args)
Do:
 srv = get_srv_records(host, proto)
if ( srv ) {
// the weight-prio algorithm calling ovpn_connect(srv_specific_args) for each of its targets
} else {
 ovpn_connect(args); // same as before
}
So, basically first there has to be a lookup against the server's SRV
record, once that lookup returned results, and the priority/weight
algorithm returns the first candidate, the existing connection mechanism
can be used to check it. If it succeeds, life goes on as it is
currently, if it fails, then the prio/weight algorithm's next target has
to be tried.

So, where should I be looking at the source that would probably be a
good place to hook this up?

We should have a design idea before doing that and a fair warning the
connnection connect logic is not for the faint hearted. In init.c is the
next_connection method that iterates through the server. Almost all
resolv related functions call openvpn_getaddrinfo, so going back from
there is also a good starting point.

And if you modify anything use -master and not 2.3 as starting point.
The code in question has changed a lot between releases (dual stack
client patches).
Definitely I'm going to use master, as I've read that's the main branch for development. Personally I think implementing a new feature in a release branch and then forward-porting it
is the wrong approach.

Regards,
-czg


Reply via email to