How to configure HTTPS proxying in Zorp 7

May 30, 2024

Abstract

This tutorial describes how to configure Zorp to proxy HTTPS traffic


Table of Contents

1. Preface
1.1. Configuring Zorp: ZMC versus Python
2. Configuring HTTPS proxying
2.1. Enabling SSL-encryption in the connection
2.2. HTTPS and non-transparent proxying
3. One-sided SSL and HTTPS
3.1. Configuring one-sided SSL
3.2. Solving problems in one-sided HTTPS connections
4. Name-based virtual hosting and Server Name Indication (SNI)
4.1. Configuring Server Name Indication (SNI)
5. Enabling Windows update
6. Python code summary
7. Summary

1. Preface

This tutorial provides guidelines for Zorp administrators on how to enable proxying HTTP traffic embedded into secure SSL and TLS connections. Knowledge in TCP/IP and Zorp administration is required to fully comprehend the contents of this paper. The procedures and concepts described here are applicable to version 7 of Zorp. Detailed information is provided to configure Zorp both from Zorp Management Console and using Python scripts.

Note that explaining the concepts of the different aspects of SSL/TLS proxying is beyond the scope of this tutorial. For background information, see the following documents:

You can download the above documents at the Balasys Documentation Page.

1.1. Configuring Zorp: ZMC versus Python

Zorp can be fully configured using either the graphical Zorp Management Console (ZMC) or manually by editing plain text Python configuration files. The suggestions and the background information provided in this tutorial are equally applicable to both methods. Step-by-step explanation with screenshots are given for ZMC-based configuration, while sample Python code lines can be found at the end of each step. After replacing the sample parameters (for example, IP addresses) with the proper ones for the actual configuration, add these lines to the policy file of Zorp (usually found under /etc/zorp/policy.py). Also pay attention to the proper indentation of Python code lines. For more details, see Chapter 10, Local firewall administration in Zorp Professional 7 Administrator Guide.

If Zorp Management Console is used and the Python code generated by ZMC needs to be displayed, select a host, then select Configuration > View from the main menu.

2. Configuring HTTPS proxying

For proxying HTTPS connections, a properly configured HTTP proxy is required. The HTTP proxy will handle the external SSL/TLS connection and analyze the HTTP traffic embedded into the encrypted SSL/TLS channel. Two basic scenarios — a transparent and a non-transparent one — will be discussed.

The best way is to derive own proxy classes from the default ones and modify their parameters as required. For details on deriving and modifying proxies, see Section 6.6, Proxy classes in Zorp Professional 7 Administrator Guide.

2.1. Procedure – Enabling SSL-encryption in the connection

Purpose: 

To proxy HTTPS connections, configure an Encryption Policy to handle SSL/TLS connections, and use this Encryption Policy in your Service. The policy will be configured to:

  • Require the client and the server to use strong encryption algorithms, the use of weak algorithms will not be permitted.

  • Enable connections only to servers with certificates signed by CAs that are in the trusted CAs list of the Zorp firewall node. (For details on managing trusted CA groups, see Section 11.3.7.3, Managing trusted groups in Zorp Professional 7 Administrator Guide.)

  • The clients will only see the certificate of Zorp. To allow the clients to access the certificate information of the server, see Procedure 2.2, Configuring keybridging in How to configure SSL proxying in Zorp 7.

Steps: 

  1. Generate a certificate for your firewall. The Zorp component requires its own certificate and keypair to perform SSL/TLS proxying.

    ZMCCreate a certificate, set the firewall as the owner host of the certificate, then distribute it to the firewall host. For details, see Chapter 11, Key and certificate management in Zorp in Zorp Professional 7 Administrator Guide.

    Python: In configurations managed manually from python, create an X.509 certificate (with its related keypair) using a suitable software (for example, OpenSSL) and deploy it to the Zorp firewall host (for example, copy it to the /etc/key.d/mycert folder).

  2. Create and configure an Encryption Policy. Complete the following steps.

    1. Navigate to the Zorp ZMC component of the firewall host.

    2. Select Policies > New.

    3. Enter a name into the Policy name field, for example, MyTLSEncryption.

      Creating a new Encryption policy

      Figure 1. Creating a new Encryption policy


    4. Select Policy type > Encryption Policy, then click OK.

    5. Select Class > TwoSidedEncryption.

      Python:

      EncryptionPolicy(
          name="MyTLSEncryption",
          encryption=TwoSidedEncryption()
          )
    6. Double-click client_certificate_generator, then select Class > StaticCertificate.

      Selecting Encryption policy class

      Figure 2. Selecting Encryption policy class


    7. Double-click the certificates and click New to add a certificate entry to a list of certificates.

      Creating a new certificate entry

      Figure 3. Creating a new certificate entry


    8. Double-click the certificate_file_path. A window displaying the certificates owned by the host will open up. The lower section of the window shows the information contained in the certificate. Select the list of certificates Zorp is required to show to the clients (for example, the certificate created in Step 1), then click Select.

      Creating a new Encryption policy

      Figure 4. Creating a new Encryption policy


      Python:

          encryption=TwoSidedEncryption(
              client_certificate_generator=StaticCertificate(
                  certificates=(
                      Certificate.fromFile(
                          certificate_file_path="/etc/key.d/ZMS_Engine/cert.pem",
                          private_key=PrivateKey.fromFile(
                              "/etc/key.d/ZMS_Engine/key.pem")
                      ),
                  )
              )
          )
    9. If the private key of the certificate is password-protected, double-click private_key_password, type the password, then click OK. Otherwise, click OK.

    10. Disable mutual authentication. That way, Zorp will not request a certificate from the clients.

      Double-click client_verify, select Class > ClientNoneVerifier, then click OK.

      Disabling mutual authentication

      Figure 5. Disabling mutual authentication


      Python:

          encryption=TwoSidedEncryption(
              client_verify=None
          )
    11. Specify the directory containing the certificates of the trusted CAs. These settings determine which servers can the clients access: the clients will be able to connect only those servers via SSL/TLS which have certificate signed by one of these CAs (or a lower level CA in the CA chain).

      Double-click server_verify, double-click ca_directory, then type the path and name to the directory that stores the trusted CA certificates, for example, /etc/ca.d/certs/. Click OK.

      Specifying trusted CAs

      Figure 6. Specifying trusted CAs


      Python:

          encryption=TwoSidedEncryption(
              server_verify=ServerCertificateVerifier(
                  ca_directory="/etc/ca.d/certs/"
              )
          )
      Note

      CAs cannot be referenced directly, only the trusted group containing them. For details on managing trusted groups, see Section 11.3.7.3, Managing trusted groups in Zorp Professional 7 Administrator Guide.

    12. Specify the directory containing the CRLs of the trusted CAs.

      Double-click crl_directory, then type the path and name to the directory that stores the CRLs of the trusted CA certificates, for example, /etc/ca.d/crls/. Click OK.

      Specifying CRLs

      Figure 7. Specifying CRLs


      Python:

          encryption=TwoSidedEncryption(
              server_verify=ServerCertificateVerifier(
                  ca_directory="/etc/ca.d/certs/",
                  crl_directory="/etc/ca.d/crls/"
              )
          )
    13. Optional Step: The Common Name in the certificate of a server or webpage is usually its domain name or URL. By default, Zorp compares this Common Name to the actual domain name it receives from the server, and rejects the connection if they do not match. That way it is possible to detect several types of false certificates and prevent a number of phishing attacks. If this mode of operation interferes with your environment, and you cannot use certificates that have proper Common Names, disable this option.

      Double-click server_verify > check_subject, select FALSE, then click OK.

      Python:

          encryption=TwoSidedEncryption(
              server_verify=ServerCertificateVerifier(
                  ca_directory="/etc/ca.d/certs/",
                  crl_directory="/etc/ca.d/crls/",
                  check_subject=FALSE
              )
          )
    14. Optional Step: Forbid the use of weak encryption algorithms to increase security. The related parameters can be set separately for the client and the server-side of Zorp, using the client_ssl_options and server_ssl_options parameters of the Encryption Policy. Disabling weak algorithms also eliminates the risk of downgrade attacks, where the attacker modifies the SSL session-initiation messages to force using weak encryption that can be easily decrypted by a third party.

      Note

      Certain outdated operating systems, or old browser applications do not properly support strong encryption algorithms. If your clients use such systems or applications, it might be required to permit weak encryption algorithms.

      1. SSL methods may occasionally fall back to older (thus weaker) protocol versions if one of the peers does not support the newer version. To avoid this situation, explicitly disable undesired protocol versions (SSLv2 and SSLv3 are disabled by default).

        For example, to disable TLSv1, double-click client_ssl_options > disable_tlsv1, click TRUE, then click OK. Repeat this step for the server_ssl_options parameter.

      Python:

          encryption=TwoSidedEncryption(
              server_ssl_options=ServerSSLOptions(
                  disable_tlsv1=TRUE)
              client_ssl_options=ClientSSLOptions(
                  disable_tlsv1=TRUE)
              )
    15. Optional Step: Enable untrusted certificates. Since a significant number of servers use self-signed certificates (with unverifiable trustworthiness), in certain situations it might be needed to permit access to servers that have untrusted certificates.

      Note

      When an untrusted certificate is accepted, the generated certificates will be signed with the untrusted CA during keybridge scenarios. For details on configuring keybridging, see Procedure 2.2, Configuring keybridging in How to configure SSL proxying in Zorp 7

      Double-click server_verifier > trust_level, click the drop-down menu and select UNTRUSTED, then click OK.

      Note

      When the trust_level value is NONE, even the invalid certificates are accepted and at the client side there is no client certificate request sent to the client.

      Python:

          encryption=TwoSidedEncryption(
              server_verify=ServerCertificateVerifier(
                  trust_level=TLS_TRUST_LEVEL_UNTRUSTED
              )
          )

    Python:

    The Encryption Policy configured in the previous steps is summarized in the following code snippet.

    EncryptionPolicy(
        name="MyTLSEncryption",
        encryption=TwoSidedEncryption(
            client_verify=ClientNoneVerifier(),
            client_ssl_options=ClientSSLOptions(),
            server_verify=ServerCertificateVerifier(
                trust_level=TLS_TRUST_LEVEL_FULL,
                intermediate_revocation_check_type =
                    TLS_INTERMEDIATE_REVOCATION_SOFT_FAIL,
                leaf_revocation_check_type =
                    TLS_LEAF_REVOCATION_SOFT_FAIL,
                trusted_certs_directory="",
                verify_depth=4,
                verify_ca_directory="/etc/ca.d/certs/",
                verify_crl_directory="/etc/ca.d/crls/",
                check_subject=TRUE
                ),
            server_ssl_options=ServerSSLOptions(),
            client_certificate_generator=StaticCertificate(
                certificates=(
                    Certificate.fromFile(
                        certificate_file_path=
                            "/etc/key.d/ZMS_Engine/cert.chain.pem",
                        private_key=PrivateKey.fromFile(
                            "/etc/key.d/ZMS_Engine/key.pem")),
                ))
        ))
  3. Select PKI > Distribute Certificates.

    Note when managing Zorp without ZMC, copy the certificates and CRLs to their respective directories. They are not updated automatically as in configurations managed by ZMC.

    By performing the above steps, the proxy has been configured to use the specified certificate and its private key, and also the directory has been set that will store the certificates of the trusted CAs and their CRLs. Client authentication has also been disabled.

  4. Create a service that clients can use to access the Internet in a secure channel. This service will use the MyTLSEncryption Encryption Policy.

    1. Select Services > New, enter a name for the service (for example, intra_HTTPS_inter), then click OK.

    2. Select Proxy class > Http > HttpProxy.

    3. Select Encryption > MyTLSEncryption.

    4. Configure the other parameters of the service as neecessary for the environment, then click OK.

    5. Select Firewall Rules > New > Service, and select the service created in the previous step. For more details on creating firewall rules, see Section 6.5, Configuring firewall rules in Zorp Professional 7 Administrator Guide.

    6. Configure the other parameters of the rule as necessary for the environment, then click OK.

    Creating a Service

    Figure 8. Creating a Service


    Python:

    def demo() :
        Service(
            name='demo/intra_HTTPS_inter',
            router=TransparentRouter(),
            chainer=ConnectChainer(),
            proxy_class=HttpProxy,
            max_instances=0,
            max_sessions=0,
            keepalive=Z_KEEPALIVE_NONE,
            encryption_policy="MyTLSEncryption"
        )
    
        Rule(
            rule_id=300,
            src_subnet=('192.168.1.1/32', ),
            dst_zone=('internet', ),
            proto=6,
            service='demo/intra_HTTPS_inter'
        )
  5. Commit and upload the changes, then restart Zorp.

    Expected result: 

    Every time a client connects to a server, Zorp checks the certificate of the server. If the signer CA is trusted, Zorp shows a trusted certificate to the client (browser or other application). If the certificate of the server is untrusted, Zorp shows an untrusted certificate to the client, giving a warning to the user. The user can then decide whether the certificate can be accepted or not.

2.2. Procedure – HTTPS and non-transparent proxying

Purpose: 

The method described in Procedure 2.1, Enabling SSL-encryption in the connection can be used when the connections of the clients are proxied transparently. In the non-transparent case, use two HttpProxy classes. (A connection is non-transparent if the clients address the firewall host directly, and Zorp selects the target.)

Steps: 

  1. Create and configure a transparent Http proxy to handle HTTPS connections as described in Steps 1-4 of Procedure 2.1, Enabling SSL-encryption in the connection. If a transparent HTTPS proxy has already been created and configured, skip this step.

  2. Navigate to Zorp > Proxies, and create a non-transparent HTTP proxy using the predefined HttpProxyNonTransparent proxy class. Name this new class, for example, HttpSProxyNonTransparent.

  3. Select this newly created proxy (for example, HttpSProxyNonTransparent) and add the self.request attribute to the Changed config attributes panel. To configure the self.request attribute, complete the following steps.

    1. Select the attribute and click Edit.

      • To accept every request types, enter the * (asterisk) character, then click OK.

      • Alternatively, you can add the request types you want to permit. It is recommended to enable the GET, POST, HEAD, and CONNECT requests.

    2. Click on the text in the Type field, then select const_http_req_accept.

  4. Add the self.connect_proxy attribute to the Changed config attributes panel, then click Edit. Select the proxy to be used for the HTTPS connections from the appearing list (for example, StrongHttpsProxy).

    Note

    This proxy is needed to handle the SSL data communicated in the plain-text nontransparent HTTP connection. If you do not want to examine that this traffic is indeed HTTP traffic, use a simple PlugProxy configured to handle SSL connections as well.

    Python:

    class HttpSProxyNonTransparent(HttpProxyNonTransparent):
        def config(self):
            HttpProxyNonTransparent.config(self)
            self.connect_proxy=StrongHttpsProxy
            self.request["*"]=HTTP_REQ_ACCEPT
  5. Create a service that clients can use to access the Internet in a secure channel. This service will use the non-transparent Http proxy class (for example, HttpSProxyNonTransparent) created in Step 2.

    Create a service that clients can use to access the Internet.

    1. Select Services > New, and enter a name for the service (for example, intra_HTTP_inter).

    2. Select Proxy class > HttpSProxyNonTransparent.

    3. Select a Router for the service. Note the following points:

      • When non-transparently proxying HTTP traffic without any parent proxy, the Service must use InbandRouter.

      • If a parent proxy is used (that is, the clients connect to a web proxy like Squid through Zorp), DirectedRouter or InbandRouter can be used. InbandRouter can only be used if the parent_proxy and parent_proxy_port parameters are properly configured. If the firewall host is located network-transparently in front of the proxy server, even TransparentRouter can be used. For further details on Routers, see Section 6.4.5, Routing — selecting routers and chainers in Zorp Professional 7 Administrator Guide.

    4. Configure the other parameters of the service as needed for your environment, then click OK.

    5. Select Firewall Rules > New > Service, and select the service created in the previous step.

      Note
      • If the clients connect directly to the firewall as a proxy, non-transparent service has to be used (using the same IP:port pair that is set on the clients).

      • If the firewall is located in front of the parent proxy used by the clients, a transparent listener has to be used, even though the proxy class used in the service is non-transparent.

    6. Configure the other parameters of the rule as needed for your environment, then click OK.

  6. Commit and upload the changes, then restart Zorp.

3. One-sided SSL and HTTPS

This section shows how to solve various tasks and problems using one-sided HTTPS connections — sometimes encryption is only required on the client (or the server) side, for example, to decrease the load on the servers (SSL-offloading).

Note that certain issues and side-effects might need to be addressed when using one-sided SSL. These are discussed in Section 3.2, Solving problems in one-sided HTTPS connections.

3.1. Procedure – Configuring one-sided SSL

Purpose: 

To disable encryption on one side of the connection for an existing Encryption Policy that is configured to handle HTTPS connections, complete the following steps.

Note

Obviously it is not possible to use keybridging together with one-sided SSL connections, but for a possible solution, see Procedure 3.2.3, Transferring certificate information in one-sided HTTPS.

Steps: 

  1. Navigate to Zorp > Proxies, and select the proxy to be modified, or create a new one (for example, OnesidedHttpsProxy).

    • To disable encryption on the client side, add the self.ssl.client_connection_security parameter to the Changed config attributes panel, then set it to const_ssl_none.

    • To disable encryption on the server side, add the self.ssl.server_connection_security parameter to the Changed config attributes panel, then set it to const_ssl_none.

    Python: Add one of the following lines to proxy:

    self.ssl.server_connection_security = SSL_NONE
    self.ssl.client_connection_security = SSL_NONE
  2. When Zorp is used to protect the servers, you must deploy the certificate of the server (including its private key) to Zorp, so that Zorp can show the certificate to the clients that connect to the server. The proxy used in the connection must be configured to use this certificate when communicating with the clients. Complete the following steps.

    1. Import the certificate of the server into ZMS, and set the firewall to be its owner host. For details, see Procedure 11.3.8.6, Importing certificates in Zorp Professional 7 Administrator Guide.

    2. Navigate to Zorp > Proxies, and select the proxy to be modified (for example, OnesidedHttpsProxy).

    3. Select (or add, if not already present) the self.ssl.server_keypair_files parameter, then click Edit.

    4. A window showing the certificates available on the host appears. Select the certificate of the server.

      Note

      The list displays only the certificates where the firewall host is set as the owner host of the certificate (that is, both the certificate and its private key is available).

3.2. Solving problems in one-sided HTTPS connections

Using absolute URLs in one-sided SSL communication can pose problems and should be avoided whenever possible (relative links will work without any problem). A URL starts with http://www... on the non-encrypted side should be https://www... on the encrypted side. Certain applications can be configured to use HTTPS links in the HTTP requests instead of normal HTTP. If your environment uses an application that cannot be configured this way, see the following procedures for a possible solution.

3.2.1. Procedure – Microsoft Outlook Web Access

Purpose: 

Outlook Web Access (OWA) can generate HTTPS links if it receives a special header in the request. This header notifies OWA that it is located behind an HTTPS frontend. Zorp can be configured to insert this header automatically. Complete the following steps.

Steps: 

  1. Navigate to Zorp > Proxies, and derive an HttpProxy class (for example, OWAHttpProxy) from an Http proxy configured to handle one-sided SSL connections.

  2. Add the self.request_header attribute to the Changed config attributes panel.

  3. Select the newly added attribute, then select Edit > New.

  4. Enter Front-End-Https for the key name. This will be the name of the header inserted into the requests.

  5. Select the Type column, then select type_http_hdr_insert.

  6. Click Edit, then select the second row (the one with qstring in its Type column).

  7. Click Edit, then enter on. This will be the content of the inserted header.

    Python:

    self.request_header["Front-End-Https"]=(HTTP_HDR_INSERT, "on")
  8. Create a service that will use this new proxy (for example, OWAHttpProxy).

3.2.2. Procedure – Using stream editor in one-sided HTTPS

Purpose: 

If a server application does not support secure connections, or uses absolute links and this behavior cannot be modified, Zorp can change the URLs in the traffic. This can be accomplished by stacking a sed (stream editor) Linux command (or if needed, a complete shell script) into the proxy.

Steps: 

  1. Navigate to Zorp > Proxies, and select the HTTP proxy configured to handle one-sided SSL connections, or create a new one (for example, HttpSedProxy).

  2. Add self.response_stack attribute to the Changed config attributes panel, then click Edit. (You need the self.response_stack attribute, because the response of the server has to be changed.)

  3. Click New, then enter *.

  4. Select the Type column, then select type_http_stk_data.

  5. Click Edit, select the row containing zorp_stack, then click Edit again.

  6. Select Stacking type > Program, and enter the command to be executed: sed -e 's|http://|https://|g'

    For details on the sed command, see the sed manual pages.

    Note

    The example sed command modifies all absolute links that appear in the traffic, that is, even links pointing to an external site will be modified. If possible, use at least the full domain name of the server in the sed command to avoid this problem (for example, sed -e 's|http://www.example.com/|https://www.example.com|g'). Be as specific as possible.

    Python:

    self.response_stack["*"]=(HTTP_STK_DATA, (Z_STACK_PROGRAM, "sed -e 's|http://|https://|g'"))
  7. Create a service that will use this new proxy (for example, HttpSedProxy).

3.2.3. Procedure – Transferring certificate information in one-sided HTTPS

Purpose: 

Client authentication in HTTPS is sometimes based on inspecting the certificate of the client. When Zorp is protecting the server, keybridging can be used to transfer the information from the client certificate to the server. However, in one-sided SSL connections (for example, if the communication between Zorp and the server is not encrypted), the server does not receive an SSL certificate, therefore user authentication must use another method. A simple solution to this problem is as follows:

Zorp requests a certificate from the client the usual way, extracts the required information from the client certificate, then inserts this information into an HTTP header. The server then authenticates the user based on the information received in the HTTP header. To accomplish this, create a special HttpProxy using the Class editor.

Steps: 

  1. Navigate to the Zorp ZMC component, and click on the Class editor icon in the menu bar.

  2. Click New, then select the General tab.

  3. Enter a name for the class (for example, HttpsCertProxy).

  4. Select Parent class > OnesidedHttpsProxy.

  5. Select Class type > proxy.

  6. Type or paste the following Python code. Based on these settings, the header of the proxy class will be generated automatically into the Source code field. You have to type the remaining part manually, or paste it from this document.

    Warning

    The source code has to confirm to the syntax requirements of the Python language. Handle indentation with great care, since in Python indentation forms the blocks of code that are on the same level (many other languages use brackets for this purpose, for example, C uses curly brackets).

    Python:

    def config(self):
        OnesidedHttpsProxy.config(self)
            self.request_header["X-User-Certificate"]=\
            (HTTP_HDR_INSERT, self.tls.client_peer_certificate.subject)
  7. Click OK and Close.

  8. Create a service that will use this new proxy (for example, HttpsCertProxy), or modify an existing one.

4. Name-based virtual hosting and Server Name Indication (SNI)

Name-based virtual hosting is a method to provide services under multiple domain names from a single server (that is, several different domain names point to the same IP address). When receiving an HTTP request, the server decides which domain should receive the connection based on the "Host" header of the HTTP request. Each domain has its own certificate for secure connections. The problem is that the SSL/TLS connection is built before the client sends the first HTTP request: the server should show the certificate of the appropriate domain before receiving the HTTP header specifying the domain name. In earlier Zorp versions, this situation was solved by either assigning a separate IP address to each domain name, or using IP aliasing. In Zorp Professional 7 and later, Server Name Indication (SNI) can be used to overcome the problem.

If IP aliasing is not feasible for some reason, Zorp can be configured to overcome this problem by modifying the target address of the connection based on information arriving in the HTTP request. This solution requires a special Http proxy.

In the following example (Procedure 4.1, Configuring Server Name Indication (SNI)), Zorp determines the target address of the HTTPS connection based on the "Host" header. Note that any other information present in the HTTP traffic can be used for such purpose. For example, it is possible to direct different GET requests to different servers (for example, requests to www.example.com are directed to Server1, but www.example.com/admin is redirected to Server2). It is also possible to use different servers to serve the static and the dynamic contents (for example, by redirecting all requests to get jpg, gif, and similar files to a separate server).

Note

Although the connections can be redirected to different servers, only a single certificate can be shown to the clients, because Zorp must send the client-side certificate to the client before the client sends the first HTTP request. Consequently, Zorp cannot determine the target address at this stage.

4.1. Procedure – Configuring Server Name Indication (SNI)

Purpose: 

To configure an HttpProxy in a name-based virtual hosting scenario that uses Server Name Indication (SNI) to determine the address of the target server, complete the following steps.

Steps: 

  1. Create and configure an Encryption Policy. Complete the following steps.

    1. Navigate to the Zorp ZMC component of the firewall host.

    2. Select Policies > New.

    3. Enter a name into the Policy name field, for example, MySNIEncryption.

    4. Select Policy type > Encryption Policy, then click OK.

      Creating an Encryption policy

      Figure 9. Creating an Encryption policy


    5. Select Class > TwoSidedEncryption.

      Configuring the Encryption policy

      Figure 10. Configuring the Encryption policy


      Python:

      EncryptionPolicy(
          name="MySNIEncryption",
          encryption=TwoSidedEncryption()
          )
  2. Double-click client_certificate_generator, then select Class > SNIBasedCertificate.

    Configuring the certificate

    Figure 11. Configuring the certificate


  3. Double-click default and click New to add a certificate entry to a list of certificates.

    Creating a new certificate entry

    Figure 12. Creating a new certificate entry


  4. Select the default certificate. Zorp will show this certificate to the clients when none of the other configured certificates match the client request.

    Python:

        encryption=TwoSidedEncryption(
            client_certificate_generator=SNIBasedCertificate(
                default=StaticCertificate(
                    certificates=(
                        Certificate.fromFile(
                            certificate_file_path="/etc/key.d/ZMS_Engine/cert.pem",
                            private_key=PrivateKey.fromFile(
                                "/etc/key.d/ZMS_Engine/key.pem")),
                    )
                )
            )
        )
  5. Configure a mapping that describes to which hostname the list of certificates belongs to. For each certificate, configure a Matcher Policy. If this policy matches the domain name in the client SNI request, Zorp shows the associated certificate to the client. Any type of matcher policy can be used here, but in most scenarios only RegexpMatcher policies will be needed. (For details on Matcher Policies, see Section 6.7.4, Matcher policies in Zorp Professional 7 Administrator Guide.)

    The following example configures two matchers and two certificates, one for the myfirstdomain.example.com domain, one for the myseconddomain.example.com domain. Complete the following steps:

    1. Double-click hostname_certificate_map, then click New.

    2. Select Class > RegexpMatcher.

    3. Click Match > New, then enter the domain name (for example, myfirstdomain.example.com) into the Expression field. Click OK.

      Configuring the hostname-certificate mapping

      Figure 13. Configuring the hostname-certificate mapping


    4. Click Edit and click New to add a certificate entry to a list of certificates.

      Creating a new certificate entry

      Figure 14. Creating a new certificate entry


    5. Double-click certificate_file_path and select the certificate to show if a client tries to access the domain set in the previous step.

    6. Click Select, then click OK.

    7. Click OK to close the list editor.

      Configuring the hostname-certificate mapping

      Figure 15. Configuring the hostname-certificate mapping


    8. Repeat from Step 'a' to Step 'e' for the myseconddomain.example.com domain and its respective certificate.

    Python:

        encryption=TwoSidedEncryption(
            client_certificate_generator=SNIBasedCertificate(
                default=StaticCertificate(
                    certificates=(
                        Certificate.fromFile(
                            certificate_file_path="/etc/key.d/ZMS_Engine/cert.pem",
                            private_key=PrivateKey.fromFile(
                                "/etc/key.d/ZMS_Engine/key.pem")),
                    )),
                hostname_certificate_map={
                    RegexpMatcher(
                        match_list=("myfirstdomain.example.com", )): StaticCertificate(
                            certificates=(
                                Certificate.fromFile(
                                    certificate_file_path="/etc/key.d/myfirstdomain/cert.pem",
                                    private_key=PrivateKey.fromFile(
                                        "/etc/key.d/myfirstdomain/key.pem")),
                            )),
                    RegexpMatcher(
                        match_list=("myseconddomain.example.com", )): StaticCertificate(
                            certificates=(
                                Certificate.fromFile(
                                    certificate_file_path="/etc/key.d/myseconddomain/cert.pem",
                                    private_key=PrivateKey.fromFile(
                                        "/etc/key.d/myseconddomain/key.pem")),
                            ))
                    },
            )
        )
  6. Configure the other options of the Encryption Policy as needed for your environment.

  7. Create a service and a firewall rule that uses this new Encryption Policy and an HttpProxy class.

    Python:

    def demo() :
        Service(
            name='demo/inter_HttpSNIService',
            router=TransparentRouter(),
            chainer=ConnectChainer(),
            proxy_class=HttpProxy,
            max_instances=0,
            max_sessions=0,
            keepalive=Z_KEEPALIVE_NONE,
            encryption_policy="MySNIEncryption"
        )
    
        Rule(
            rule_id=300,
            src_subnet=('internet', ),
            dst_zone=('dmz', ),
            proto=6,
            service='demo/inter_HttpSNIService'
        )

5. Procedure – Enabling Windows update

Purpose: 

To enable Windows update for the clients protected by the firewall, you have to import the certificate of the Zorp CA that signs the certificates in keybridging into the client machines. To accomplish this, complete the following steps on the client hosts.

Note

An alternative to this solution is to disable SSL-proxying for the v4.windowsupdate.microsoft.com domain. This method is described in detail in the Technical Tutorial Proxying secure channels — the Secure Socket Layer. The advantage of the alternative method is that you do not need to modify the client hosts.

Prerequisite: 

You will need the certificate of the Zorp CA that signs the certificates in keybridging into the client machines. Export this certificate from ZMS, and make it available on your client hosts.

Steps: 

  1. Start the Microsoft Management Console (Start Menu > Run application > MMC).

  2. Select File > Add/Remove Snap-in.

  3. Click Add, then select Certificates.

  4. Select Computer account, then click Next.

  5. Select Local computer and click Finish. The Certificates module has been added to the Console Root tree.

  6. Expand the Certificates node, then expand the Trusted Root Certification Authorities node. Right-click on the Certificates node, select All Tasks, then click Import.

  7. Click Next on the Welcome to the Certificate Import Wizard page. On the File to Import page, click Browse, and locate the certificate of the Zorp CA to be imported.

  8. On the Certificate Store page, accept the default setting (Place all certificates in the following store), click Next, then Finish.

    Note

    Zorp must be able to verify the certificates of the Windows Update servers. To accomplish this, the certificates of the certificate authorities (CAs) issuing the certificates of the Windows update servers have to be imported into Zorp, if not already present. The following certificates have to be imported:

    • Microsoft Secure Server Authority

    • Microsoft Internet Authority

    • GTE CyberTrust Global Root

6. Python code summary

When configured according to this tutorial, the policy.py file of Zorp should look something like this:

Configuring HTTPS proxying:

class HttpsProxy(HttpProxy):
    def config(self):
        HttpProxy.config(self)
        self.ssl.client_keypair_files=\
             ("/etc/key.d/Certificate_for_SSL_proxying/cert.pem",\
             "/etc/key.d/Certificate_for_SSL_proxying/key.pem")
        self.ssl.client_verify_type=SSL_VERIFY_NONE
        self.ssl.client_connection_security = SSL_FORCE_SSL
        self.ssl.server_connection_security = SSL_FORCE_SSL
        self.ssl.server_cagroup_directories= \
             ("/etc/ca.d/groups/ZMS_Trusted_CA/certs/",\
              "/etc/ca.d/groups/ZMS_Trusted_CA/crls/")
        self.ssl.server_disable_proto_sslv2=TRUE

Nontransparent version:

class HttpSNonTransparent(HttpProxyNonTransparent):
    def config(self):
        HttpProxyNonTransparent.config(self)
        self.connect_proxy= HttpsProxy
        self.request["GET"]=HTTP_REQ_ACCEPT
        self.request["POST"]=HTTP_REQ_ACCEPT
        self.request["HEAD"]=HTTP_REQ_ACCEPT
        self.request["CONNECT"]=HTTP_REQ_ACCEPT

One-sided HTTPS and Microsoft Outlook Web Access:

class OnesidedHttpsProxy(HttpsProxy):
    def config(self):
        HttpsProxy.config(self)
        self.ssl.server_connection_security=SSL_NONE
        self.ssl.server_keypair_files = \
            ("/etc/key.d/Sample Certificate/cert.pem",\
             "/etc/key.d/Sample Certificate/key.pem")
        self.stack_proxy=(Z_STACK_PROXY, OWAHttpProxy)

class OWAHttpProxy(HttpProxy):
    def config(self):
        HttpProxy.config(self)
        self.request_header["Front-End-Https"]=(HTTP_HDR_INSERT, "on")

HTTP Proxy using stream editor

class HttpSedProxy(OnesidedHttpsProxy):
    def config(self):
        OnesidedHttpsProxy.config(self)
        self.response_stack["*"]=(HTTP_STK_DATA, (Z_STACK_PROGRAM, "sed -e 's|http://|https://|g'"))

Transferring certificate information in an HTTP header

class HttpsCertProxy(OnesidedHttpsProxy):
    def config(self):
        OnesidedHttpsProxy.config(self)
        self.request_header["X-User-Certificate"]=(HTTP_HDR_INSERT, self.tls.client_peer_certificate.subject)

Name-based virtual hosting and sidestacking:

class HttpProxyTargetByHostHeader(HttpProxy):
    def config(self):
        HttpProxy.config(self)
        self.request_header["Host"]=(HTTP_HDR_POLICY, self.TargetByHostHeader)
        self.ssl.client_connection_security=SSL_FORCE_SSL
        self.ssl.server_connection_security=SSL_NONE
        self.ssl.server_keypair_files = \
            ("/etc/key.d/Sample Certificate/cert.pem",\
             "/etc/key.d/Sample Certificate/key.pem")
    def TargetByHostHeader(self, name, value):
        if (value == "example.com"):
          self.session.setServer(SockAddrInet("192.168.0.1", 80))
          return HTTP_HDR_ACCEPT
        elif (value == "example2.com"):
          self.session.setServer(SockAddrInet("192.168.0.2", 80))
          return HTTP_HDR_ACCEPT
        return HTTP_HDR_ABORT

7. Summary

This tutorial has shown how to configure Zorp to proxy HTTPS traffic, including scenarios where only one side of the traffic is encrypted. Although these examples are relatively simple, they provide a solid base from which more complex configurations can be built — just as the security policy of your organization requires it.[1]



[1] All questions, comments or inquiries should be directed to or by post to the following address: BalaSys IT Ltd. 1117 Budapest, Alíz Str. 4 Phone: +36 1 646 4740 Web: https://www.balasys.hu/

Copyright © 2024 BalaSys IT Ltd. All rights reserved.

The latest version is always available at the Balasys Documentation Page.