Fortiweb Cookbook: Most Basic Setup - One website, HTTP only, Round Robin load balancing between two physical servers, all protections on Alert only, Host header filtration


Task: publish website yurisk.com, hosted on 2 physical servers: server1 (10.10.10.13) and server2 (10.10.10.14). The site should be available on HTTP only, no HTTPS. Apply preconfigured protection Inline Alert Only. The website's IP address visible to clients is 192.168.13.92.

Solution.

Configuration flow:

fortiweb-basic-setup

Step 1: Create Virtual IP on which Fortiweb will listen for incoming HTTP connections. Network -> Virtual IP -> Create .... For the name I use VIP-yurisk-com, IP is 192.168.13.92, and the interface via which this IP is reachable is port1.
NOTE: some objects in Fortiweb do not allow dots in their names, so, to be consistent, I am using dashes where a dot would normally go. Also, you cannot change the name of any created object later - to change the name, you have to delete this object and re-create from scratch.

fortiweb basic setup create virtual ip

Step 2: Use the VIP in creating new Virtual Server.

Server Objects -> Server -> Virtual Server -> New ..

fortiweb basic setup create virtual server

Step 3: (Optional, but recommended) Create Protected Hostnames so to apply all the protections for HTTP requests with valid Host headers only, namely yurisk.com and www.yurisk.com. Any other (and therefore invalid) requests will be dropped. This configuration is optional but recommended as saves Fortiweb resources. All the protections/checks are applied in order, and checking the Host: header is done very early in the processing. This way many requests done by bots/crawlers/scanners which try to brute force available virtual hosts on the web servers will be blocked before Fortiweb applies additional protections to them.

Server Objects -> Protected Hostnames -> Create New .... Default Action: Deny. This means for all NON-matching Host: headers listed below drop the requests. If, on the other hand, we wanted to block some hosts but allow other, we would set Default Action to Accept, and then would set Accept or Deny in each hostname configured.

fortiweb basic setup create protected hostnames

Step 4: Create Server Pool to represent our 2 physical servers: Server Objects -> Server Pool -> Create New.... For this type of set up (HTTP servers), we'll use Create HTTP Server Pool as oppsed to ADFS or FTP. Regarding the Type - as this Fortiweb is operating in the Reverse Proxy Mode (used probably in 90% of all the installations and is most feature-rich), the server pool has to be Reverse Type as well.
Single Server vs Server Balance: I prefer to use Server Balance even if the pool actually has just one member server. This is for the case additional servers are added later.

Server Health Check: I'll be using preconfigured one HLTHCK_HTTP which checks that the physical server is responding for the website requests.

Load Balancing Algorithm: Round Robin.

Persistence: None, as I haven't created Persistence Policy.

fortiweb basic setup create server pool

NOTE: If the object configuration is multi-step, as here, you have to do the 1st step, click on OK, and only then it will allow to continue to step 2.

Create New: After saving the work done above, we can create 2 physical servers with their real IP addresses (10.10.10.13 and 10.10.10.14), state (Enabled/Disabled/Maintenance), listening port (80), Health Check Domain Name - I set it to yurisk.com, and leave the rest with defaults.

Create physical server:

fortiweb basic setup create server pool

Final result should look like that:

fortiweb basic setup create server pool

Step 5: Use all the created so far to create a Server Policy.

Policy -> Server Policy -> Create New -> Create HTTP Policy...

Deployment Mode: Single Server/Server Pool (Content Routing is used to route clients based on any of the HTTP multiple parameters, you can look at an example here: Fortiweb Cookbook: content routing based on URL configuration example).

Virtual Server: vsrv-yurisk-com

Server Pool: srv-pool-yurisk-com

Protected Hostnames: hostnames-yurisk-com

HTTP Service: HTTP (If we wanted the Fortiweb to listen ona custom port, say 3123, we would first create such custom service and then would put it instead of built-in HTTP).

Web Protection Profile: Inline Alert Only

fortiweb basic setup create server policy

NOTE: In Reverse Proxy mode of operation, which is our case, without a Server Policy allowing the traffic, all requests to the physical web servers would be blocked.

Verification

Let's browse to the website yurisk.com to see if it works. Pay attention as I press F5 to refresh, I reach each time the other server in the server pool due to the Round Robin balancing method we set earlier:

Note: This video has no sound.

Now let's try to reach some non-existent on those servers domain. I will try to reach some web site by IP only - 192.168.13.92. Without Protected Hostnames setting it would work, as default Apache install listens for all unknown domains as well. But Fortiweb blocks this attempt:

Note: This video has no sound.

Regarding Health checks of the servers in a pool - here is tcpdump on the physical server side how such checks look:

root@ubuntu1:~# tcpdump -n -c 5 -vv -i any port 80 

    10.10.10.74.33230 > 10.10.10.13.80: Flags [P.], cksum 0x8f39 (correct), seq 1:175, ack 1, win 8030, length 174: HTTP, length: 174
        HEAD / HTTP/1.1
        Accept: */*
        Accept-Language: en
        Content-Type: text/html
        Host: yurisk.com
        User-Agent: HealthCheck
        Server-pool: srv-pool-yurisk-com
        Connection: close

In the next episodes I will add local and LDAP user authentication to access the website, and HTTPS as one of the protocols.

Add web site authentication with local and remote (LDAP) users
Add HTTPS protocol support for SSL offloading.

CLI configuration of all the above

config system vip
  edit "VIP-yurisk-com"
    set vip 192.168.13.92/32
    set interface port1
    set index 1
  next
end


config server-policy vserver
      edit "vsrv-yurisk-com"
        config  vip-list
          edit 1
            set vip VIP-yurisk-com
          next
        end
      next
    end

    config server-policy allow-hosts
      edit "hostnames-yurisk-com"
        set default-action deny
        config  host-list
          edit 1
            set host www.yurisk.com
          next
          edit 2
            set host yurisk.com
          next
        end
      next
    end


    config server-policy server-pool
      edit "srv-pool-yurisk-com"
        set server-balance enable
        set health HLTHCK_HTTP
        set server-pool-id 15152185382089931844
        config  pserver-list
          edit 1
            set ip 10.10.10.13
            set server-id 14833377406792437432
            set hlck-domain yurisk.com
          next
          edit 2
            set ip 10.10.10.14
            set server-id 13115127060638259350
            set hlck-domain yurisk.com
          next
        end
      next
    end


    config server-policy policy
      edit "srv-policy-yurisk-com"
        set vserver vsrv-yurisk-com
        set service HTTP
        set web-protection-profile "Inline Alert Only"
        set replacemsg Predefined
        set server-pool srv-pool-yurisk-com
        set allow-hosts hostnames-yurisk-com
        set policy-id 16091469981553709465
        config  http-content-routing-list
        end
      next
    end

Follow me on https://www.linkedin.com/in/yurislobodyanyuk/ not to miss what I publish on Linkedin, Github, blog, and more.