Updating IPV4 and IPV6 on a VPN connection

May 9, 2010 at 11:01 AM

Hi Jeff,

First of all, some awesome work on this project, I started looking at your code Friday evening and by Saturday had a completed project. My project takes a list of VPN details from a database and creates / updates the VPN connections on a local machine, it will update the usernames / passwords, remote VPN server address, whether to use the default gateway etc. etc. I have an issue though which I don't know if it's a bug, I can modify items such as Use Default Remote Gateway by doing :

entry.Options |= ~RasEntryOptions.RemoteDefaultGateway;
OR
entry.Options |= RasEntryOptions.RemoteDefaultGateway;

however when I try to manipulate the "use IPV4 / IPV6" (under networking protocols) entries it will only allow me to take them away, never add them back in again :

entry.NetworkProtocols |= ~RasNetworkProtocols.IPv6; // This will work just fine and will remove IPV6 from the list of protocols
BUT
entry.NetworkProtocols |= RasNetworkProtocols.IPv6; // This never adds IPV6 back into the list

The same goes for IPV4.

Could you shed some light on it? I'm using V1.1 but couldn't see anything in the recent builds that points to a fix so haven't tried V1.2, I'm using the 2008 DLL and I'm on Win7.

Thanks
Matt

 

 

Coordinator
May 9, 2010 at 3:20 PM

This is why I ripped out all those stupid flags for the 1.2 version in favor of a class with booleans on it. Even I hate working with flags, the syntax is annoying and half the time I forget how to do it due to lack of needing to do it myself. Why this happens, I do not know - but I think it's a syntax issue with the code we've been using.

entry.Options |= ~RasEntryOptions.RemoteDefaultGateway;

If you watch the entry.Options value, after using that code the flag doesn't understand what represents all the values. Intellisense displays entry.Options equals 4294967295 instead of showing the flag names with RemoteDefaultGateway removed.

entry.Options = entry.Options & ~RasEntryOptions.RemoteDefaultGateway;

This code will work correctly and allow you to manipulate the flags properly.

Jan 18, 2012 at 7:44 AM

Sorry to bring up an old thread, but I'm having a similar issue--

I'm using version 1.2 however whenever I set the RemoteDefaultGateway option, it sets all the IPv4 and IPv6 addresses to "Use the following address" instead of "Obtain address automatically".

Is there a workaround for this issue?

Jan 18, 2012 at 10:15 AM

Hi Shadow,

I still have this for my code, it is working even though I still have the IPV6 commented out. I just leave the defaults and it seems to work. :

    // Don't try to use this VPN connection's credentials on all web pages etc.
    entry.ExtendedOptions = entry.ExtendedOptions & ~RasEntryExtendedOptions.DoNotUseRasCredentials;

    // Use Default Gateway ?
    if (row["vpnDefaultGW"].ToString().ToUpper() == "NO")
    {
        entry.Options = entry.Options & ~RasEntryOptions.RemoteDefaultGateway;
    }
    else
    {
        entry.Options = entry.Options & RasEntryOptions.RemoteDefaultGateway;
    }

    /* This is disabled because there's a bug in the DLL
    // Use IP V6
    if (row["vpnIPV6"].ToString().ToUpper() == "NO")
    {
        entry.NetworkProtocols = entry.NetworkProtocols & ~RasNetworkProtocols.IPv6;
    }
    else
    {
        entry.NetworkProtocols = entry.NetworkProtocols & RasNetworkProtocols.IPv6; // Never works !?!
    }
    entry.Update();


    // Use IP V4
    if (row["vpnIPV4"].ToString().ToUpper() == "NO")
    {
        entry.NetworkProtocols = entry.NetworkProtocols & ~RasNetworkProtocols.IP;
    }
    else
    {
        entry.NetworkProtocols = entry.NetworkProtocols & RasNetworkProtocols.IP;  // Never works !?! 
    }*/

    entry.Update();

That was written for an old version of the DLL which had bugs but still works well under 1.2. As to whether you can uncomment that code in the new V1.2 I don't know.

Maybe that helps a little ?

Best Regards

Matt

 

Coordinator
Jan 18, 2012 at 2:55 PM

I'm out sick right now so I won't be putting too much time into any responses. Just be patient and give me a couple days and I'll get back to you. Maybe you've found a bug, not sure at this point. It could just be a nuance with Windows that I need to document on the properties you're working with. Once I finish getting over this virus I'll do some investigation on the matter.

Also, the area you're talking about right now has been completely revamped for 1.2 to address the problem with a lot of users not knowing how to work with flag enums in .NET. Granted it's not an excuse, but the enums seemed to be causing more harm than good with other users accidentally removing all the flags that needed to be set.

- Jeff

Jan 18, 2012 at 7:36 PM

@DrummerBoy, I'll see about those properties - they'vechanged a bit (flags to booleans) since v1.2.

 

@Jeff_winn, Hope you get better soon! Im not requiring an urgent fix or anything so please take your time! The connects still seem to work with blank IP addresses, it just might confuse the user or have a roll-on effect im not aware of.

Coordinator
Jan 21, 2012 at 2:29 AM

Shadow,

What version of Windows are you using including service pack? Also is it 32-bit, 64-bit, or both?

Also, which version of DotRas are you using? (WIN2K, WINXP, WIN2K8, WIN7)?

I also found a couple bugs which may be related to your situation...

1) The IPv6RemoteDefaultGateway option was not persisting correctly to the phonebook.

2) The IPv6DnsAddress and IPv6DnsAddressAlt properties were causing false positives thinking you were specifying addresses when you weren't.

3) The IPv6Address property was also causing a false positive thinking an address had been specified when it hadn't.

Do these sound like the problems you've been seeing? I couldn't replicate any problems with the IPv4 section of the TCP/IP settings.

- Jeff

Jan 21, 2012 at 3:07 AM
Edited Jan 22, 2012 at 9:15 PM

Hi Jeff,

Thanks for getting back to me :)

I'm using DotRas WIN7 under Windows 7 Pro 64-Bit SP1.

I think all those bugs might be relevant to the issue that I'm experiencing. Whenever setting the [IPv6]RemoteDefaultGateway, the IPv6DNSAddress (but also IPv4 and other Address fields) seem to think they've been set, and show in the Windows VPN dialog as blank IP Addresses like in the following picture; http://imgur.com/Tmwq6.

-- Jake

Coordinator
Jan 21, 2012 at 3:43 AM

Jake,

I checked the IPv4 settings during testing repeatedly couldn't replicate it there at all even before I put the patch in. Check the IPAddress, DnsAddress, and DnsAddressAlt properties on RasEntry. Are you doing anything special with any of those properties?

How is the entry being created, through the Windows user interface, manually, or using the RasEntry.CreateVpnEntry method?

You can try grabbing the source code from either trunk or the 1.2 branch, both have the patch I put in place for the bugs I mentioned above if you want to see if the SP1 patch fixes your remaining problem. I'd suggest creating a new entry to ensure that the existing one hasn't been corrupted somehow.

Jan 22, 2012 at 9:21 PM

Jeff,

I just downloaded and tested the 1.2 branch and trunk; however the issue is still present.

I'm editing existing Phonebook entries, including new ones made from the Windows VPN, using the following code in phonebook loop;

entry.Options.RemoteDefaultGateway = False
entry.Options.IPv6RemoteDefaultGateway = False

entry.Update()

It changes the Remote Default Gateway option, which is as expected. Interestingly, it seems having a blank IP in the Windows Dialog doesn't actually affect the operation of the VPN -- as there is no IP specified, it still connects without complaint using an "automatically obtained" address.

So it's not a critical bug, however as it will be run on multiple machines, I prefer to have it edit the VPN entries consistently.

Thanks,

Jake

Coordinator
Jan 23, 2012 at 6:24 AM

Found it, looks like the values were being read from the phonebook as 0.0.0.0, and when you called update on them again the value was doing an equality check that was returning false which was causing it to tell the entry that an IP address was specified.

Just had to fix the method that does the checks internally so it could handle values correctly.

IPAddress addr1 = IPAddress.Parse("0.0.0.0");

bool equals = (addr1 == IPAddress.Any);  // false
bool equals = addr1.Equals(IPAddress.Any); // true

That's what was causing the problem in the equality check.

Coordinator
Jan 23, 2012 at 6:33 AM

You can get latest again, should resolve the last remaining problem.

- Jeff

Jan 23, 2012 at 7:05 AM

Great, trunk works fine!!

I was wondering, also, what would you recommend for importing and exporting all the entries in the personal phonebook? I tried a routine to duplicate the pbk, however Windows didn't seem to like that (didn't pick up the changes, I assume a log off and on would fix that, but regardless isn't suitable). Should I be iterating through the phonebook and exporting/serializing the entries into a BinaryFormatter or similar?

What are your thoughts?

Thanks,

Jake

Coordinator
Jan 23, 2012 at 1:45 PM

Well, RasEntry is non-serializable for it's dependencies on the RasPhoneBook as well as other associated data (ie. EAP, passwords, etc) that isn't stored on the entry itself. So trying to serialize it using any kind of serializer will cause an exception to be thrown, which this was the intended behavior. Depending on where you're trying to copy the entries to could cause problems with Windows. There are two phonebooks actively in use by Windows, the all-users phonebook and the current user. Entries shouldn't be duplicated between them because Windows may have problems being able to distinguish between them on the Windows network connections user interface.

I suppose a good question would be why are you trying to duplicate the phonebook? If all you're wanting to do is make a copy of it, do a File.Copy on the PBK file that's stored on the file system. Regardless, even if you do attempt to duplicate the phonebooks using File.Copy, you'll never get access to all the data without having to call each method to get access to the additional data associated with the entry, and even then you won't get access to all of it.

- Jeff

Jan 23, 2012 at 7:43 PM
Edited Jan 23, 2012 at 9:34 PM

Ah, I wondered if that might be the case; that it doesn't store everything in once place. Hmm, it's pretty essential, so I might implement ISerializable around and try and store as much as possible.

The case in particular is that we have 15+ VPN connections, which need to be available on each computer, and adding each one manually is just unnecessarily time consuming and cumbersome. The VPN Connections themselves, however, are quite simple, just a username, password, address but otherwise everything else can be set to default. I'm thinking that I could check the existing phonebook for duplicates, and work that way, Creating RAS until all the entries are present.

Thoughts?

-- Jake

Jan 23, 2012 at 7:43 PM
Edited Jan 23, 2012 at 7:44 PM

Sorry, dupe post :)

Coordinator
Jan 23, 2012 at 9:30 PM

The PBK files can be transferred between machines, assuming the same hardware is available on all target machines. In the case of VPNs, the WAN miniports used are always available (except for SSTP introduced in Windows 7 and is not backwards compatible right now). The only thing you'd be missing for each of your connections then is the credentials. Creating your own dial-up manager app which stores the PBK file next to it for portability also ensures that your 15+ VPN connections don't show up in the standard Windows dial-up connections list. You'd just need to decide how you wanted to store the credentials, and use a RasDialer instance to handle dialing the connection asynchronously. Your users would simply have to use your app to connect rather than using the Windows dial-up connection window.

As for making a non-serializable class serializable, I would HIGHLY advise against doing so. Like I said, the RasEntry class isn't serializable simply because I forgot, it had to be for it to work correctly. Any changes to the code I wrote that aren't published on here is going to put you in an unsupported state with the project, and you'll just be on your own to fix any problems. If you really have to serialize the object, create your own object and transfer the information to it and serialize that. That will meet your need while still keeping you in a supported state with this project. Not to mention if my API changes (which it probably will) you'll be less dependent on DotRas allowing for easier upgrades.

As for apps like what you mentioned above, the only comment I will make is I will never implement a solution in DotRas that circumvents security put in place by Microsoft. Also, I'd appreciate it if you edit your post and remove the link so I don't have to delete the post, I don't want anyone believing that this project condones those types of tools.

Thanks!

- Jeff

Jan 23, 2012 at 9:44 PM

Jeff,

When I say serializable, I mean making my own object to hold the data. I'm not going to sift through all the DotRas code and implement serialization, that would take ages! I'd prefer to keep the Windows dialer.

As for the passwords, I wasn't asking you to implement it into DotRas, it was merely a workaround for what isn't available with the PBKs. I've removed the link for you.

-- Jake

Coordinator
Jan 24, 2012 at 3:11 AM

Hmm, well I'm not sure what more I help I can give you. Sounds like you've got a pretty solid direction you want to take with your project. If you want to store the credentials with the entry just make sure the entry exists in a phonebook prior to calling UpdateCredentials on the entry. This is due to the credentials being stored in that separate location as I mentioned earlier.

With the severity of the bugs you found (thank you for reporting them btw) I'll probably be pushing out a service pack release to 1.2 around Feb 1st if you'd be interested in getting on a build and not having to compile the project yourself.

Also, thanks for removing that link for me!

- Jeff