[translation] run the flash application on HTTPS

Time:2021-7-27

translate
Running Your Flask Application Over HTTPS

introduce

In the process of developing flash applications, the development web server is usually run, which provides a basic but fully functional WSGI HTTP server. However, when deploying an application to a production environment, one of the things to consider is whether the client should be required to use an encrypted connection to increase security.

So how should I run a flash application over HTTPS? In this article, I will introduce several options for adding encryption to flash applications, from a very simple solution that can be implemented in only 5 seconds to a robust a + rated solution.

[translation] run the flash application on HTTPS

How does HTTPS work?

The encryption and security functions of HTTP are implemented through transport layer security (TLS) protocol. In general, TLS defines a standard way to ensure the security of network channels.

The basic idea is that when the client establishes a connection with the server and requests an encrypted connection, the server will use itSSL certificateRespond. The certificate acts as the identity of the server because it includesServer name and domain。 To ensure that the information provided by the server is correct, the certificate is encrypted and signed by a certification authority (CA). If the client understands and trusts the Ca, it can confirm that the certificate signature really comes from this entity, and through this client, the client can determine that the server it connects to is legal.

After the client validates the certificate, it creates an encryption key for communication with the server. To ensure that this key is sent securely to the server, it uses the public key contained in the server certificate to encrypt it. The server has the private key used with the public key in the certificate, so it is the only party that can decrypt. Since the server receives the encryption key, all traffic is encrypted with a key known only to the client and server.

In order to implement TLS encryption, we need two entries: server certificate, including the public key signed by CA; The private key along with the public key contained in the certificate.

The simplest way

Flask (more specifically, Werkzeug) supports the use of on the fly certificates, which is very useful for quickly serving applications over HTTPS without certificates.

To use a temporary certificate on flask, you need to install an additional dependency in the virtual environment:

$ pip install pyopenssl

Then SSL_ Context = ‘ad hoc’ is added to app. Run() call:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(ssl_context='adhoc')

If you are using the flash 1. X release, you can also use this option through the flash cli:

$ flask run --cert=adhoc

When running this script (or   flask run  ) , You will notice that flask indicates that it is runninghttps://server:

$ python hello.py
 * Running on https://127.0.0.1:5000/ (Press CTRL+C to quit)

However, the problem is that browsers do not like this type of certificate, so they will display a terrible warning, which you need to remove before accessing the application. Once you allow the browser to connect, you will have an encrypted connection, just as you get from a valid certificate server. Using these temporary certificates can be easy to test, but it is not suitable for any practical purpose.

Self signed certificate

The so-called self signed certificate is a certificate that generates a signature using the private key associated with the certificate. I mentioned above that the client needs to “know and trust” the CA signing the certificate, because this trust relationship enables the client to verify the server certificate. Web browsers and other HTTP clients pre configure the list of known and trusted CAS, but obviously, if a self signed certificate is used, the CA will not be known and the verification will fail. This is exactly what happened with the temporary certificate we used in the previous section. If the web browser cannot verify the server certificate, it allows you to continue and access the problematic website, but it will remind you of the risks you need to take.

[translation] run the flash application on HTTPS

But is there really a risk? Using the last part of the flash server, you obviously believe in yourself, so there is no risk for you. The problem is that this warning appears when users connect to sites they do not know or control. In this case, the user will not know whether the server is real or not, because anyone can generate certificates for any domain.

Although self signed certificates are sometimes useful, temporary certificates in flask are not very good because different certificates are generated through pyopenssl every time the server runs. When using a self signed certificate, it is best to use the same certificate every time you start the server, because this can configure the browser to trust it and eliminate security warnings.

You can generate a self signed certificate from the command line by simply installing OpenSSL:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365

This command writes a new certificate in cert.pem and its corresponding private key in key.pem. The validity period is 365 days.
When you run this command, several questions are asked:

Generating a 4096 bit RSA private key
......................++
.............++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Oregon
Locality Name (eg, city) []:Portland
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Miguel Grinberg Blog
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

Now, we can use this new self signed certificate in the flash application by using SSL in app. Run ()_ The context parameter is set to a tuple containing the file names of the certificate and private key files.

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
    return "Hello World!"
if __name__ == "__main__":
    app.run(ssl_context=('cert.pem', 'key.pem'))

If you are using flash 1. X or later, you can add — cert and — key options to the flash run command:

$ flask run --cert=cert.pem --key=key.pem

The browser will still alarm, but if you check the certificate, you will see the information you entered when you created it

[translation] run the flash application on HTTPS

Using the production web server

We all know that the flash development server is only suitable for development and testing. So how do we install SSL certificates on production servers?

If you use gunicorn, you can use the command line parameters:

$ gunicorn --certfile cert.pem --keyfile key.pem -b 0.0.0.0:8000 hello:app

If you use nginx as the reverse proxy, you can use nginx to configure the certificate, and then nginx can “terminate” the encrypted connection, which means that it will accept the encrypted connection from the outside, but then use the regular unencrypted connection to communicate with the flash back-end. This is a very useful setting because it eliminates the need for applications to handle certificates and encryption. The configuration items of nginx are as follows:

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    # ...
}

Another important issue you need to consider is how to deal with clients connected through regular http. In my opinion, the best solution is to respond to unencrypted requests by redirecting to the same URL but using HTTPS. For a flash application, you can implement it through the flash sslify extension. Using nginx, you can include another server block in the configuration:

server {
    listen 80;
    server_name example.com;
    location / {
        return 301 https://$host$request_uri;
    }
}

Use real certificate

Unless the browser has studied the limitations of these certificates, it will not tell us that these certificates still exist.

Therefore, for production sites, the best choice for server certificates is to obtain them from one of these well-known CAS that are automatically trusted by all web browsers.

When you request a certificate from a Ca, the entity will verify that you are under the control of the server and domain, but the way of verification depends on the ca. If the server passes this verification, the CA will issue a certificate with its own signature and give it to you for installation. The certificate is usually valid for no more than one year. Most CAS charge for these certificates, but some provide certificates free of charge. The most popular free Ca is calledLet’s Encrypt

Getting a certificate from let’s encrypt is fairly easy because the whole process is automated. Suppose you are using an Ubuntu based server, you need to install their open source certbot tool on your server:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install certbot

Now you can use the certbot tool to request certificates. Certbot can validate your site in a number of ways.

In general, the “Webroot” method is the easiest to implement. Using this method, certbot adds some files to the directory exposed by the web server as static files, and then tries to access them over HTTP using the domain for which the certificate is to be generated. If this test is successful, certbot knows that the server running it is associated with the correct domain, matches it, and issues a certificate. The command to request a certificate using this method is as follows:

$ sudo certbot certonly --webroot -w /var/www/example -d example.com

In this example, we try to generate a certificate for the example.com domain, which uses the directory in / var / www / example as the static file root. Unfortunately, flash based websites do not have a static file root. At least when using the default configuration, they use the / static prefix to access all static files in the application, so more planning is needed.

In this example, we try to generate a certificate for the example.com domain, which uses the directory in / var / www / example as the static file root. Unfortunately, the flame based web site does not have a static file root (at least when using the default configuration), and you need to use the / static prefix to access all static files in the application.

Certbot’s operation on the static root directory is to add a. Well-known subdirectory and store some files in it. It then uses the HTTP client to  [http://example.com/.well-known/...](http://example.com/.well-known/...) Retrieve these files in the form of. If you can retrieve these files, your server completely controls the domain name. For flask and other applications that do not have a static file root directory, it is necessary to define a root directory.

If nginx is used as a reverse proxy, you can provide certbot with a private directory where its authentication files can be written with powerful mappings that can be created in the configuration. In the following example, I extended the HTTP server block shown in the previous section to send all encryption related requests (always starting with /. Well-known /…) to a specific directory of your choice:

If nginx is used as the reverse proxy, the powerful mapping created in the configuration can provide certbot with a private directory where it can write its authentication files

server {
    listen 80;
    server_name example.com;
    location ~ /.well-known {
        root /path/to/letsencrypt/verification/directory;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}

Then you can give this directory to certbot:

$ sudo certbot certonly --webroot -w /path/to/letsencrypt/verification/directory -d example.com

If certbot can verify the domain name, it will write the certificate file as / etc / letsencrypt / Live / example.com/fullchain.pem and the private key as / etc / letsencrypt / Live / example.com/privkey.pem, which is valid for 90 days.

To use this newly obtained certificate, you can enter the two file names mentioned above instead of the self signed file we used earlier, which should apply to any configuration described above. Of course, you also need to make your application available through your registered domain name, because this is the only way for the browser to accept the certificate as valid.

When you need to update your certificate, you can also use certbot:

$ sudo certbot renew

If any certificates in the system are about to expire, the above command will update them and leave a new certificate in the same location. If you want to get the updated certificate, you may need to restart your web server.

Obtain SSL a + level

If you use let’s encrypt or other known CA certificates on the production site and run the latest maintained operating system on this server, you are likely to have a server with the highest score in SSL security. You can go to  Qualys SSL LabsLaboratory website to get a report.

The report will point out where you need to improve, but generally speaking, I hope you will be told that the encryption communication options disclosed by the server are too wide or too weak, making you vulnerable to known vulnerabilities.

One of the things that is easy to improve is how to generate the coefficients used in the encryption key exchange process, which usually have fairly weak default values. In particular, Diffie Hellman coefficients take a lot of time to generate, so by default, the server uses a smaller number to save time. But we can pre generate strong coefficients and store them in a file, and then nginx can use them. Using the OpenSSL tool, you can run the following commands:

openssl dhparam -out /path/to/dhparam.pem 2048

If you want a stronger coefficient, you can change 2048 above to 4096. This command takes some time to run, especially if your server does not have a lot of CPU power, but when it runs, you will have a dhparam.pem file with strong coefficients. You can insert the SSL server block of nginx

ssl_dhparam /path/to/dhparam.pem;

You may need to configure the password that the server allows encrypted communication. This is the list on my server:

ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

In this list, use! Prefix disable ciphers  。 The SSL report will tell you if there are any passwords that are not recommended. You must check from time to time to determine if new vulnerabilities requiring modification of this list have been found.

Below you can find my current nginx SSL configuration, including the above settings, and some warnings I added to the SSL report:

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ssl_dhparam /path/to/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_protocols TLSv1.2;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;
    # ...
}

You can see the SSL security report obtained from my website. If you don’t score 100% in all categories, you must add other restrictions to the configuration, but this will limit the number of clients that can connect to your site. In general, older browsers and HTTP clients using ciphers are not considered the strongest, but if you disable ciphers, these clients will not be able to connect. Therefore, you basically need to compromise, and you also need to regularly check the safety report and update it as the situation changes.

Unfortunately, for the complexity of these recent SSL improvements, you will need to use professional web servers, so if you don’t want to use nginx, you need to find a server that supports these settings, and the list is very small. I know Apache can, but I don’t know anything else.