How to set a static IP (client side) in OpenVPN?

I am setting up a VPN network with a lot of little devices (running OpenWRT). In my use case, the devices are all identified by a number and I would like their ip adresses to match their ID (e.g: the device number 6 will have an ip in X.X.X.6).

I am aware of client-config-dir and ifconfig-push but i cannot use them because all my devices use the same certificate (duplicate-cn is enabled). This is a requirement since generating one certificate for each devices will be too constraining (moreover, we don't want to change the configuration of the VPN server if we add a device in the system)

Is it possible to set the ip adress in the client configuration file ? I didn't found anything in the documentation about that particular topic... And everything I tried didn't succeed.

Basically, what I have in mind would be the following:

  • Client Connect to the VPN server and asks for a specific adress ("give me the ip: 172.16.0.22")
  • If the adress is already taken, the handshake fails. If it is free, the client is given the adress he asked before

Solution 1:

You should be able to do this with the ifconfig-pool-persist config option. You can pre-configure the file and set seconds = 0 to tell OpenVPN to only read the file.

We use it to ensure the same user is assigned the same IP when connected via VPN for audit purposes.

From the man page:

--ifconfig-pool-persist file [seconds] Persist/unpersist ifconfig-pool data to file, at seconds intervals (default=600), as well as on program startup and shutdown. The goal of this option is to provide a long-term association between clients (denoted by their common name) and the virtual IP address assigned to them from the ifconfig-pool. Maintaining a long-term association is good for clients because it allows them to effectively use the --persist-tun option.

file is a comma-delimited ASCII file, formatted as ,.

If seconds = 0, file will be treated as read-only. This is useful if you would like to treat file as a configuration file.

Note that the entries in this file are treated by OpenVPN as suggestions only, based on past associations between a common name and IP address. They do not guarantee that the given common name will always receive the given IP address. If you want guaranteed assignment, use --ifconfig-push

Solution 2:

Suppose we are setting up a company VPN, and we would like to establish separate access policies for 3 different classes of users:

System administrators -- full access to all machines on the network
Employees -- access only to Samba/email server
Contractors -- access to a special server only

The basic approach we will take is (a) segregate each user class into its own virtual IP address range, and (b) control access to machines by setting up firewall rules which key off the client's virtual IP address.

In our example, suppose that we have a variable number of employees, but only one system administrator, and two contractors. Our IP allocation approach will be to put all employees into an IP address pool, and then allocate fixed IP addresses for the system administrator and contractors.

Note that one of the prerequisites of this example is that you have a software firewall running on the OpenVPN server machine which gives you the ability to define specific firewall rules. For our example, we will assume the firewall is Linux iptables.

First, let's create a virtual IP address map according to user class:

Class   Virtual IP Range    Allowed LAN Access  Common Names  

Employees   10.8.0.0/24     Samba/email server at 10.66.4.4     [variable]

Sys Admins  10.8.1.0/24     Entire 10.66.4.0/24 subnet  sysadmin1

Contractors 10.8.2.0/24     Contractor server at 10.66.4.12     contractor1, contractor2

Next, let's translate this map into an OpenVPN server configuration. First of all, make sure you've followed the steps above for making the 10.66.4.0/24 subnet available to all clients (while we will configure routing to allow client access to the entire 10.66.4.0/24 subnet, we will then impose access restrictions using firewall rules to implement the above policy table).

First, define a static unit number for our tun interface, so that we will be able to refer to it later in our firewall rules:

dev tun0

In the server configuration file, define the Employee IP address pool:

server 10.8.0.0 255.255.255.0

Add routes for the System Administrator and Contractor IP ranges:

route 10.8.1.0 255.255.255.0
route 10.8.2.0 255.255.255.0

Because we will be assigning fixed IP addresses for specific System Administrators and Contractors, we will use a client configuration directory, ccd:

client-config-dir ccd

Now place special configuration files in the ccd subdirectory to define the fixed IP address for each non-Employee VPN client, as follows.

ccd/sysadmin1 file:

    ifconfig-push 10.8.1.1 10.8.1.2

ccd/contractor1 file:

    ifconfig-push 10.8.2.1 10.8.2.2

ccd/contractor2 file:

    ifconfig-push 10.8.2.5 10.8.2.6

Each pair of ifconfig-push addresses represent the virtual client and server IP endpoints. They must be taken from successive /30 subnets in order to be compatible with Windows clients and the TAP-Windows driver. Specifically, the last octet in the IP address of each endpoint pair must be taken from this set:

[  1,  2] [  5,  6] [  9, 10] [ 13, 14] [ 17, 18]
[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38]
[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58]
[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78]
[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98]
[101,102] [105,106] [109,110] [113,114] [117,118]
[121,122] [125,126] [129,130] [133,134] [137,138]
[141,142] [145,146] [149,150] [153,154] [157,158]
[161,162] [165,166] [169,170] [173,174] [177,178]
[181,182] [185,186] [189,190] [193,194] [197,198]
[201,202] [205,206] [209,210] [213,214] [217,218]
[221,222] [225,226] [229,230] [233,234] [237,238]
[241,242] [245,246] [249,250] [253,254]

This completes the OpenVPN configuration. The final step is to add firewall rules to finalize the access policy.

Source: https://openvpn.net/index.php/open-source/documentation/howto.html#policy