Overkill pfsense build and setup and some tips hotel setup

  • thank you to pfsense its awesome community, i'd like to give back with whatever i can here are my 2 cents.

    I went though few pfsense routers from amazon that didnt work out so well for the long run.
    Mini ITX pfSense Firewall with 64Gb SATA SSD Pre loaded with Version 2.1/64 Bit Intel D2500CC 4Gb DDR3 RAM 2x Gbe Intel LAN Ports
    Mini ITX pfSense Router/Firewall with 5x Gbe LAN, 32Gb SATA SSD pre-loaded with 64 bit pfSense 2.1

    anyways to the point, finally i got enough courage to build one my self.
    I bought all the parts from newegg.com ( i was in rush and just sort of put together a PC, I could have done a lot of things differently, do your own homework if you plan to build one your self, there are cheaper alternatives, )

    (CPU) 1 x ($184.99) Intel Core i5-4430 Haswell Quad-Core 3.0GHz LGA 11 $184.99
    (RAM) 1 x ($123.99) G.SKILL Ripjaws X Series 16GB (2 x 8GB) 240-Pin DD $123.99
    (Mother Board) 1 x ($99.99) GIGABYTE GA-Z97-HD3 (rev. 1.0) LGA 1150 Intel Z97 $99.99
    (Power Supply) 1 x ($54.99) Thermaltake TR2 TR-600 600W ATX12V v2.3 SLI Ready $54.99
    (HD - SSD) 1 x ($52.99) Kingston SSDNow V300 Series SV300S37A/120G 2.5" 12 $52.99
    (2 Network Cards) 2 x ($37.99) Intel PWLA8391GT Desktop Adapter PRO/1000 GT 10/ 1 - OEM $75.98
    (Tower) 1 x ($17.99) DIYPC DIY-BJ05BK Black ATX and Micro-ATX Mid Tower $17.99

    here are steps for people to follow

    Find a USB Stick that you can throw it away if need be.
    Download PFSense https://www.pfsense.org/download/mirror.php?section=downloads
    Even though i bought a intel CPU and the options at the download page are AMD64 (64-bit) or i386 (32-bit) still select the AMD64 (64-bit)
    go to https://doc.pfsense.org/index.php/Writing_Disk_Images this explains how to make the USB bootable with the image
    for windows you need Win32 Disk Imager, its simple little tool, hard to get lost but follow steps on pfsense writing disk images guide if you need help
    so far you have downloaded the pfsense 64 bit and you made a bootable usb stick

    plug in the usb stick and boot the computer,
    let pfsense boot all the way after that the menu will ask you to to type 99 to install to disk, google up the install guide if you need help with the install.

    if people need help, ask, ill explain things i know if not others will pick it up.
    here is my setup and if you need detail explanation i will explain it.

    I own a hotel
    I have 2 LAN networks and 1 WAN network
    1 LAN Network is attached to switch and 2 Access Points are attached to the same switch.
    the other LAN is for my priv use
    Lan 1 is setup with
    PrivLan is setup with

    DHCP server is setup on both network

    Captive Portal is setup on LAN network with Voucher Auth.
    I followed this form https://forum.pfsense.org/index.php?topic=41658.15
    to get voucher length to be shorter


    First generate a key "openssl genrsa 31 > key.private"
    Then openssl rsa -pubout < key.private >key.public
    Roll bits: #5 (This can be more but we didn't have to use many different rolls)
    Ticket bits: #16
    Checksum bits: #5

    i removed letter i from vouchers and all the UPPER CASE LETTERS
    The reason why i removed all the upper case letters is because my voucher auth page forces all letters to be lower case because there are some phones that make the 1st letter CAPITAL and i get lots of complains that the wifi code isnt working, so i forced all letters to be lower case. here is my index page
    i'd like to clearly state that i am one of those copy paste guy, i know what i am doing but its because i copy paste and able to understand basic stuff, i couldnt write this on my own, i have no idea where i got it from, but its bits and peaces from here and there to make it work for what i need done.

    <form method="post" action="$PORTAL_ACTION$" onsubmit="return CheckBoxesValidations() ;"> 
    	<title>NAME OF YOUR COMPANY</title>
    # Please Log-in to use NAME OF YOUR COMPANY WiFi

    this index page uses CSS here is the .css code

    body {
      -webkit-background-size: cover;
      -moz-background-size: cover;
      -o-background-size: cover;
      background-size: cover;
      font-family: 'Roboto', sans-serif;
    .login-card {
      padding: 40px;
      width: 274px;
      background-color: #F7F7F7;
      margin: 0 auto 10px;
      border-radius: 20px;
      box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
      overflow: hidden;
    .login-card h1 {
      font-weight: 100;
      text-align: center;
      font-size: .9em;
    .login-card input[type=submit] {
      width: 100%;
      display: block;
      margin-bottom: 5px;
      position: relative;
    .login-card input[type=text], input[type=password] {
      height: 44px;
      font-size: 16px;
      width: 100%;
      margin-bottom: 10px;
      -webkit-appearance: none;
      background: #fff;
      border: 1px solid #d9d9d9;
      border-top: 1px solid #c0c0c0;
      /* border-radius: 2px; */
      padding: 0 8px;
      box-sizing: border-box;
      -moz-box-sizing: border-box;
      text-align: center;
    .login-card input[type=text]:hover, input[type=password]:hover {
      border: 1px solid #b9b9b9;
      border-top: 1px solid #a0a0a0;
      -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
      -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
      box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
    .login {
      text-align: center;
      font-size: 14px;
      font-family: 'Arial', sans-serif;
      font-weight: 700;
      height: 36px;
      padding: 0 8px;
    /* border-radius: 3px; */
    /* -webkit-user-select: none;
      user-select: none; */
    .login-submit {
      /* border: 1px solid #3079ed; */
      border: 0px;
      color: #fff;
      text-shadow: 0 1px rgba(0,0,0,0.1); 
      background-color: #4d90fe;
      /* background-image: -webkit-gradient(linear, 0 0, 0 100%,   from(#4d90fe), to(#4787ed)); */
    .login-submit:hover {
      /* border: 1px solid #2f5bb7; */
      border: 0px;
      text-shadow: 0 1px rgba(0,0,0,0.3);
      background-color: #357ae8;
      /* background-image: -webkit-gradient(linear, 0 0, 0 100%,   from(#4d90fe), to(#357ae8)); */
    .login-card a {
      text-decoration: none;
      color: #666;
      font-weight: 400;
      text-align: center;
      display: inline-block;
      opacity: 0.6;
      transition: opacity ease 0.5s;
    .login-card a:hover {
      opacity: 1;
    .login-help {
      width: 100%;
      text-align: center;
      font-size: 12px;

    i attached how it looks like

    ill edit this as I remember more things to add later on, if you have any questions related to my setup ill be able to answer it,

  • Hello very nice post. I've been searching so long to find a solution but I couldn't find anything related on the forums nor the web so I would hope you can help me with my struggles.

    I am trying to make a custom captive portal page but I ran into some problems. I am wondering where did you upload the css file? As I am looking at your code the css is not embedded into the html file. Can you please give me some details on how you went into inserting pictures and css into the captive portal page. I know there are some options where you can embed pictures into HTML by converting it to base64 and embed css into html as well but that just didn't work well for me (at least the photos did not).

    So my real question is if there is a directory to which I can upload my custom captive_portal.html and styles.css and photos for the captive portal page.

    Appreciate the help :)


  • LAYER 8 Netgate

    Use the captive portal file upload function.

    If you upload customcss.css it will be available as captiveportal-customcss.css.

    Reference that file in your custom portal html page.

  • Just to clarify, every file you upload via the uploader on the captive portal config pages will be renamed "captiveportal-filename.file", where the uploaded file is "filename.file". So every reference to a picture or css file in the body of your captiveportal html file has to have the prefix "captiveportal-" in front of the original filename. The custom captive portal page itself is uploaded on the main CP paqe in the 'Portal Page contents' section.

  • I managed to make a very nice responsive design with a time lapse video for the background. I compressed the video down 5 MB and I see the uploading limit is 1 MB. Is there a way I would be able to upload it in a different way? Maybe through the Diagnostics/Command Prompt/Upload? I tried that and it successfully uploaded the video to tmp directory. So is there a way to move it to captive portal directory or should I reference to tmp somehow, if so what is the full path.

  • LAYER 8 Netgate

    The captive portal upload files are limited to 1MB total because they are all encoded and stored in the config.xml.

    You will want to whitelist another HTTP server and store your heavy files there and refer to the external server in your portal page.

    Note that when you get lots of clients who show up with devices that have not gone through the portal yet still make bunches of connections to port 80 sites - incessantly because they're lame - you can get quite a load on your portal. Lighter is usually better no matter how pretty it looks. You might consider a pretty after-authentication URL instead. Externally-hosted "heavy" files should lighten the load on the portal server. nginx seems to be much better than lighttpd in this regard anyway.

    Note that "external" doesn't have to mean off-site out on the internet. You could have a DMZ-type solution with an nginx/apache server. Another unbound DNS server wouldn't be a bad idea either.

  • I've pretty the same setup - hotel and everything.

    Not using voucher - but room + password login (using the local pfSEnse user manager, we are not selling Internet access, so I can apply the rule : keep it simple).

    One important thing was missing in your write up: the firewall rules for the OPT1 (Captive portal) interface !!!
    See the image below for a simple setup.
    I'll explain the rules :

    1. I'll block all SMTP (port 25) outgoing trafic. If needed, I can explain why. Just do it and you won't regret it.
    2. The alias "Poweredge" contains the IP of a syslog server in my LAN. this rules allows UDP trafic only (== syslog) from my AP's in the portal network to this server. APx is an alias for my 5 IP's used by my AP's present in the Captive Portal's network.
    3. The AP's CAN communicate with the Internet, for their time, update , whatever they want to do.
    4. The pfSense portal interface is pingable
    5. I have two "air-print" printers, so portal visitors that can 'find' these printers (alias 'Printers' contains the IP of those two printers) can use these pribnter toi …. printer (You'll be needing the package Avahi !!) - this rule is experimental ...
    6. "ThisFirewallPorts" (alias for 21,22,23,80,443) blocks all direct access to these ports on the pfSense Captive portal's interface.
    7. "NetBIOSPorts" (alias for 135,137,139, 445) are not going anywhere ..... (traffic isn't routable anyway)
    8. Visitors can't connect to the WAN adress of pfSense
    9. Still there , Then the visitor may pas to the net ONLY (but not my LAN !).
    10. Safety rule : block the rest.

    Btw : the issue : devices capitalize the first letter of a voucher or login name.
    For years, I patched the pfSense portal code so the first letter was first to lowercase ...
    Today, my login "user"  is the room number, like "205" so this issue doesn't bug me (the client, actually) anymore.
    But : I regret the issue. People came down to the reception and telling me : "I can't logging, the password (all the same for ALL rooms) isn't good. "
    So I negotiated a deal :

    • If I can make it work, you pay me a bear.
    • If there is a problem with the network, you'll have to wait a little bit, I'll make it work, and I pay you a bear.
      The client always accepted, and I always left my work drunk - I never paid a bear in my live for a client :)

    (Some clients understood the issue, so I advised them to su Apple ... or Samsung, beause it was their browser in their BJOD that forces the upper case character - it's NOT a pfSense  issue.)

  • LAYER 8 Netgate

    Hey, Gertjan, it looks to me like you can replace this rule:

    Block TCP source PORTAL net dest PORTAL address ports ThisFirewallPorts


    Block IPv4 any source PORTAL net dest This Firewall (self)

    Without impacting users at all and reducing the possibility something leaks.

    I don't see any DNS rules. If that service is local it would have to be passed higher in the rule set like with ping.

    And with the above the WAN address block could be deleted.

  • Are you sure that rule 9 will restrict traffic to LAN ? In pic it miss destination !LAN net

  • @Derelict:

    Hey, Gertjan, it looks to me like you can replace this rule:
    Block TCP source PORTAL net dest PORTAL address ports ThisFirewallPorts
    Block IPv4 any source PORTAL net dest This Firewall (self)
    Without impacting users at all and reducing the possibility something leaks.

    Are you sure ?
    Because, as you said :

    I don't see any DNS rules. If that service is local it would have to be passed higher in the rule set like with ping.

    If I add ports "53" or even "This Firewall (self)" then I have to make an explicit pass rule for TCP/UDP traffic to the DNS server (pfSense) - as for ping - as you said.

    Readability would be better, I guess.


    And with the above the WAN address block could be deleted.

    It's more a "full stop" line, useless, I know, because the final hidden rule will do the same.

    Thanks for the suggestions.

    PS : I changed rule 7 to block "This firewall" - any ports (and acivate the logging for this rule)
    I did NOT add any DNS pass rule.
    Captive portal still works …... no firewall rule logs where syslogged.
    DNS cache in my iPhone ?

  • LAYER 8 Netgate

    That is the pass to the internet rule. It shouldn't restrict anything. That's why I don't use !LAN net rules (except where it makes perfect sense). Makes the rule set too unclear.

  • @n3by:

    Are you sure that rule 9 will restrict traffic to LAN ? In pic it miss destination !LAN net

    You were right, uploaded the wrong image - thanks making that clear.

  • LAYER 8 Netgate

    You only need the DNS pass rules if the clients are configured to use something on the firewall for DNS. If they're set to use, for example, google they'll be passed by the pass any any internet rule.

  • Ok, got it.
    @Derelict : I saw that you can move, and thus separate posts, is it possible that you separate my post (edit : and move it to the Captive portal forum), and all the replies ?

    Right now, I have the impression I polluted the initial post of itson - things went HS ….

Log in to reply