bnhf / openvpn-admin-plus

Docker-based web interface (with golang backend) for monitoring and admin of an OpenVPN TAP/TUN server setup with PiVPN or other OpenVPN server installations. This project has been renamed from pivpn-tap-web-ui, to reflect its new broader scope.
MIT License
143 stars 23 forks source link

Password for the new user configuration when connecting #8

Closed karabelnikov closed 1 year ago

karabelnikov commented 1 year ago

There is no field in the web interface for specifying a password when creating a new user configuration. You can implement a field in which there will be a check, if the field is empty, then the user password for the new user configuration is not created. If you specify a password, the profile will be created using this password. And when connecting, the user will need to enter a password for his configuration. This improves the security of using profiles in a productive environment and helps prevent profile theft or unauthorized connection. Here is a screenshot of what it might look like.

Снимок экрана 2022-12-07 221923

bnhf commented 1 year ago

@karabelnikov

This is a good idea, and I'll have a think on how I want to implement it. No timeline at the moment, but I'll let you know.

karabelnikov commented 1 year ago

Okay, friend. Thank you. I'll be waiting. I am very interested in this project. I will continue to explore it and offer ideas or edits.

bnhf commented 1 year ago

@karabelnikov

Maybe you could help with a little research. It appears EasyRSA has been enhanced to support some sort of command line password passing in the form: ./easyrsa --passout=file:passfile --passin=file:capassfile build-client-full $cn But I haven't found any documentation on how to use it. There's also mention of environment variables -- but again no detail.

Referenced here: https://www.appsloveworld.com/bash/100/15/using-easy-rsa-how-to-automate-client-server-creation-process

Let me know if you come across anything that explains how these options work, hopefully with some examples.

karabelnikov commented 1 year ago

Scott, here is a discussion of this functionality in the automatic installation script that I use. Perhaps you can get some useful information from here: https://github.com/angristan/openvpn-install/issues/389 There also seems to be a solution here, but as I understand it, it has not been tested: https://github.com/angristan/openvpn-install/pull/1015/commits/c7d8455631572d9eaab2bffedce4eeae07995554

As I understand it, the script should look like this. There is a form in which there are 2 fields, 1 name field, 2 passphrase field. The loop checks both fields during the request and, based on their data, passes the easyrsa command to generate a certificate with or without a password. If with a password. Then you need the form to transmit the data of the passphrase field, through a temporary file or something else. This is not an easy task, but it is very interesting and necessary in our project.

karabelnikov commented 1 year ago
echo "The password for client was already set"
PASSPHRASE="pass:${PASSPHRASE}"
./easyrsa --passin=$PASSPHRASE --passout=$PASSPHRASE build-client-full "$CLIENT" 

I think these lines are key and will tell you about the implementation. You need to set the $PASSPHRASE variable, which will pass the password from the form to the certificate creation command if the condition of another cycle is met that the certificate creation command with a passphrase is separated.

bnhf commented 1 year ago

@karabelnikov

There also seems to be a solution here, but as I understand it, it has not been tested: angristan/openvpn-install@c7d8455

I'd seen the discussion you referenced, but not the PR, so good work on referencing that!

The following appears to function from the command line, assuming a password environment variable set to PASSPHRASE and client name set to CN:

easyrsa --passin=pass:$PASSPHRASE --passout=pass:$PASSPHRASE build-client-full $CN

Looks like something we can work with. :-)

karabelnikov commented 1 year ago

I agree! This is the code we need: easyrsa --passin=pass:$PASSPHRASE --passout=pass:$PASSPHRASE build-client-full $CN

Also, for the $PASSPHRASE variable, a check must be made in the field. If $PASSPHRASE is empty, the command is passed: easyrsa build-client-full $CN

if the user was specified characters in the $PASSPHRASE variable field, this means installing a passphrase on a new profile and the command is passed: easyrsa --passin=pass:$PASSPHRASE --passout=pass:$PASSPHRASE build-client-full $CN

You can also make a small check of the $PASSPHRASE field for the minimum number of characters, let's say at least 6 characters, which will increase the security of the profiles being created. You know, most people are lazy to set cryptographic passwords, which ultimately undermines security. 😊

bnhf commented 1 year ago

@karabelnikov

I edited your comment immediately above, as you had a few stray spaces in the commands -- just in case somebody comes across this thread and tries to use them.

bnhf commented 1 year ago

@karabelnikov

OK, I've implemented this feature, and have done some basic testing. Would you mind giving it a more complete run-through? As before, I've built a fresh multi-arch container with the "beta" tag. This also includes the changes to the way the DNS fields work in Configuration - OpenVPN config. If you could test clients with and without passphrase encryption, that would be great!

karabelnikov commented 1 year ago

Scott, I've tested it and I can tell you about the results:

Problem 1. If you try to create a user with an empty name, then for some reason the Passphrase field is also checked, although this should not be, because this field is optional for input. But it is also highlighted in red as an error.

Problem 2. If you create a user by specifying a name and an empty passphrase, then a user profile is created, but adding it to the OpenVPN Connect program when connecting, it asks for a password for some reason. But I clearly did not specify the password, it remained empty. However, he still demands it. Apparently, the "nopass" parameter is passed incorrectly when creating a profile.

Problem 3. If you create a user by specifying a name and a passphrase, then a user profile is created, but when you connect in the OpenVPN Connect program and enter a passphrase, writes an error and the connection does not occur. Apparently he doesn't like the passphrase. But I'm sure I'm entering a passphrase, right. I set a simple passphrase: 12345678. However, the error goes out and the connection does not occur.

Problem 4. When entering a passphrase into a string when creating a user profile, the password is displayed explicitly. This does not meet the security requirements. It is necessary that when entering a password, the characters "dots" are displayed instead of a passphrase, for example: • • • • • •

What are your ideas?

karabelnikov commented 1 year ago

Scott, most likely we misinterpreted the line: easyrsa --passin=pass:$PASSPHRASE --passout=pass:$PASSPHRASE build-client-full $CN

I found the following information: The password to the key is transmitted via the -passion option. Openssl supports several password transfer schemes:

--passin pass:Password - the password Password is set directly on the command line --passin env:PWD_VAR - the password is set in the environment variable PWD_VAR --passin file:/path/to/key/pwd.txt - the password is set in the file /path/to/key/pwd.txt --passin stdin - read password from /dev/stdin --passin fd:6 - read password from file descriptor 6

Example: sudo \ openssl ca -batch -config /etc/openvpn/keys/safessl-easyrsa.cnf \ -out /tmp/keys/client.crt -in /tmp/keys/client_unpass.crt \ -keyfile /etc/openvpn/keys/private/ca.key -passin pass:Password \ -cert /etc/openvpn/keys/ca.crt

Here is the detailed information https://www.openssl.org/docs/man1.1.1/man1/openssl.html#Pass-Phrase-Options

karabelnikov commented 1 year ago

As I understand it:

The --passin parameter is used to decrypt or remove the passphrase from the example.key The --passout parameter is used to set a passphrase on the example.key They are not used at the same time. We didn't get it right, so it doesn't work right for us :)

I understand that in our case it is necessary: easyrsa --passout=pass:$PASSPHRASE build-client-full $CN

karabelnikov commented 1 year ago

The --passout parameter is used to set a passphrase on the key. In our case, it is exactly what you need to use. The --passin parameters is used to remove the passphrase from the key.

bnhf commented 1 year ago

@karabelnikov

Thanks for testing Shura, sorry we didn't have a better result. One interesting takeaway is that clearly a password was set, even when we didn't want one. :-) I'll play around with the syntax on the command line again, but this time I'll test the resulting client package -- even if it generates without error.

bnhf commented 1 year ago

@karabelnikov

The --passout parameter is used to set a passphrase on the key. In our case, it is exactly what you need to use. The --passin parameters is used to remove the passphrase from the key.

Nice job on the research! I've just confirmed the above, including connecting remotely using the generated .ovpn file. Where did you end up finding this correct syntax?

karabelnikov commented 1 year ago

Scott, I've been on the Internet for a long time looking for the information we need. There is no detailed documentation on this issue, I agree. Somewhere in the discussions on the forums, after analyzing the discussions there, I came to this conclusion. Examples of creating a key with a passphrase and decrypting it were also given. I realized that we went a bit the wrong way, these parameters are used in different ways and cannot be used together.

This is a very exciting adventure :)

bnhf commented 1 year ago

@karabelnikov

A very exciting adventure indeed!

I did more extensive testing this time, to be sure the generated encrypted and non-encrypted configurations were working properly. So far so good, though as before I look forward to feedback from you. Of the problems you listed, I believe I have addressed 1 thru 3.

Number 4 though, is functioning as I intended. My thinking is that rather than enforcing password field parameters, that this is treated more as an encryption key. If the field was masked, it would be very easy to mistype the passphrase -- so then we're immediately talking about adding password unmasking or a second password field for verification.

It could be done of course, but my preference would be to leave it as is. Simple, but effective, when combined with the need to have the .ovpn or .zip file on hand, and the ability to revoke any suspect certificate packages.

The new multi-arch beta just finished building and uploading, so feel free to pull and kick it around a bit. Thanks again.

bnhf commented 1 year ago

@karabelnikov

I understand that in our case it is necessary: easyrsa --passout=pass:$PASSPHRASE build-client-full $CN

Also, a final note on the above, despite some of what I saw online about needing to use environment variables -- it's not necessary. The passphrase can be placed directly in the above command along with the client name.

karabelnikov commented 1 year ago

Scott, I have tested everything and I can say with confidence that the point of the problem from 1 to 3 is solved and everything works as it should! Great job!

However, I have a suggestion for improvement. I think you'll like it too. Firstly, the form can be simplified and the fields can be made in the form of a table with columns of equal size. Secondly, add a hint in the field placeholder="Enter name for new certificate" and placeholder="Enter password for new private key" for greater clarity.

Thirdly, as I suggested earlier, in order to secure data entry (as it is implemented with the "Password" fields), make the input secret with characters (this is achieved by specifying <input type="password"> and setting the eye icon so that you can change <input type="text">. It will look very nice and correct, if necessary, the user can click on the eye icon and check the password entry and click again to hide it.

I think it's a great idea to complete the strokes with this functionality! Screenshots are attached!

Снимок экрана 2022-12-10 181931

Снимок экрана 2022-12-10 181957

bnhf commented 1 year ago

@karabelnikov

Thanks for testing. I'm going to go ahead and merge what's been done so far into the main branch and build a new "latest" container. I like your suggestions for putting the name and passphrase fields side-by-side and adding masking with a reveal button. Would you be willing to submit this as a PR to the newly merged code base?

karabelnikov commented 1 year ago

@bnhf I did it! I will offer all edits via PR.

Снимок экрана 2022-12-11 003329 Снимок экрана 2022-12-11 003355 Снимок экрана 2022-12-11 003415

bnhf commented 1 year ago

@karabelnikov

Shura, the new beta is available with your PR merged, and it mostly looks good. However, there is an issue with the Create New Certificate box. Name and Passphrase are right next to each other in my browser (Chrome):

Screenshot 2022-12-10 154722

Also, there's no unmask icon showing up in the Passphrase field. You can ignore the little white and green Roboform icon, that's just offering to fill the password.

karabelnikov commented 1 year ago

@bnhf

Scott, you just need to clear the cache and cookies in the browser history. Most likely, the updated custom.css is not being pulled up and therefore styles have not been applied.

bnhf commented 1 year ago

@karabelnikov

Right you are, I just needed to clear "Cached images and files" in Chrome. Thanks! Looks great.

karabelnikov commented 1 year ago

@bnhf

I made a few changes to the custom.css style to correct the width of the cells. It looks better now. I suggested it through PR.

Attention! To view changes with styles, you should always remember to clear the browser cache and cookies. Sometimes I forget about it myself :)

bnhf commented 1 year ago

@karabelnikov

There's a new container with the "beta" tag available that incorporates your PRs from today. Looks good -- thanks.