{"id":622,"date":"2020-11-23T19:32:24","date_gmt":"2020-11-23T19:32:24","guid":{"rendered":"https:\/\/dft.wiki\/?p=622"},"modified":"2025-04-27T18:21:38","modified_gmt":"2025-04-27T22:21:38","slug":"high-availability-with-carp-in-pfsense","status":"publish","type":"post","link":"https:\/\/dft.wiki\/?p=622","title":{"rendered":"High Availability with CARP and VRRP"},"content":{"rendered":"<p><strong>CARP<\/strong> (Common Address Redundancy Protocol) is an alternative protocol to <strong>VRRP<\/strong> (Virtual Router Redundancy Protocol), and the Cisco proprietary <strong>HSRP<\/strong> (Hot Standby Router Protocol).<\/p>\n<p><strong>BSD<\/strong> systems extensively use <strong>CARP<\/strong> while <strong>Linux<\/strong> systems prefer using <strong>VRRP.<\/strong><\/p>\n<p>The objective is to make two different gateways respond to the same IP. This is done by creating a Virtual IP, that is different than the IP used by both routers, to decide who will be active and who will be on standby.<\/p>\n<p>In a network where two routers <code>10.0.0.2<\/code> and <code>10.0.0.3<\/code> communicate over CARP and define who will respond to the Virtual IP <code>10.0.0.1<\/code>. When the active becomes inoperative the standby takes place.<\/p>\n<hr \/>\n<p><strong>ON PFSENSE WEB-UI<\/strong><\/p>\n<p>On the Master, go to <strong>Firewall &gt; Virtual IPs<\/strong>:<\/p>\n<ul>\n<li>Click in &#8220;<strong>+ Add<\/strong>&#8220;,<\/li>\n<li>Select the &#8220;<strong>Type<\/strong>&#8221; as &#8220;<strong>CARP<\/strong>&#8220;,<\/li>\n<li>Select the &#8220;<strong>Interface<\/strong>&#8221; of the LAN,<\/li>\n<li>Define the Virtual IP address in &#8220;<strong>Address(es)<\/strong>&#8220;, for example <code>10.0.0.1<\/code> and mask <code>\/24<\/code>,<\/li>\n<li>Define the &#8220;<strong>Virtual IP Password<\/strong>&#8220;,<\/li>\n<li>Leave the <strong>VHID<\/strong> as &#8216;<strong>1<\/strong>&#8216; for the first, but if you already have one virtual IP, choose another number,<\/li>\n<li>The &#8220;<strong>Description<\/strong>&#8221; can be &#8216;<strong>LAN Default Gateway<\/strong>&#8216; for example,<\/li>\n<li>Click on &#8220;<strong>Save<\/strong>&#8220;, then &#8220;<strong>Apply Changes<\/strong>&#8220;.<\/li>\n<\/ul>\n<p>If you did the HV Sync [<a href=\"https:\/\/dft.wiki\/?p=620\">Read It<\/a>], you don&#8217;t have to do the same at the Slave.<\/p>\n<p>If the Virtual IP was created to the WAN interface, you will have to go to <strong>Firewall &gt; NAT &gt; Outbound<\/strong>:<\/p>\n<ul>\n<li>Chose the &#8220;<strong>Outbound NAT Mode<\/strong>&#8221; for &#8220;<strong>Hybrid<\/strong>&#8220;,<\/li>\n<li>Click on &#8220;<strong>Save<\/strong>&#8220;, then &#8220;<strong>Apply<\/strong> <strong>Changes<\/strong>&#8220;,<\/li>\n<li>Click on &#8220;<strong>+ Add<\/strong>&#8220;,<\/li>\n<li><strong>In the table &#8220;Edit Advanced Outbound NAT Entry<\/strong>&#8220;, add in &#8220;<strong>Source<\/strong>&#8221; the Network address of the LAN, for example, <code>10.0.0.0\/24<\/code>,<\/li>\n<li>At the table &#8220;<strong>Translation<\/strong>&#8221; &gt; &#8220;<strong>Address<\/strong>&#8221; select the &#8220;<strong>WAN Virtual IP<\/strong>&#8220;,<\/li>\n<li>Enter a &#8220;<strong>Description<\/strong>&#8220;, such as &#8216;<strong>WAN Virtual IP for NAT<\/strong>&#8216;,<\/li>\n<li>Click on &#8220;<strong>Save<\/strong>&#8221; and &#8220;<strong>Apply Changes<\/strong>&#8220;.<\/li>\n<\/ul>\n<p>This will prevent the loss of the packets during the transition to the Slave.<\/p>\n<hr \/>\n<p><strong>ON LINUX<\/strong><\/p>\n<p>In Linux systems, VRRP can be accomplished using the tool <strong>KeepAliveD<\/strong> [<a href=\"https:\/\/github.com\/acassen\/keepalived\">link<\/a>].<\/p>\n<p>Installation in all redundant instances in the cluster.<\/p>\n<pre>sudo apt update\r\nsudo apt install keepalived -y\r\nsudo nano \/etc\/keepalived\/keepalived.conf<\/pre>\n<p>In summary, by configuring all redundant instances in the pool as follows assuming the interface name is <code>eth0<\/code>.<\/p>\n<p><strong>Primary<\/strong><\/p>\n<pre>vrrp_instance <strong>VirtualIP01<\/strong> {\r\n    state <strong>MASTER<\/strong>\r\n    interface <strong>eth0<\/strong>\r\n    virtual_router_id <strong>999<\/strong>\r\n    priority <strong>100<\/strong>\r\n    advert_int <strong>1<\/strong>\r\n    authentication {\r\n        auth_type PASS\r\n        auth_pass <strong>7bd3a2aa-f49b-11ef-8b04-ff74caed956a<\/strong>\r\n    }\r\n    virtual_ipaddress {\r\n        <strong>10.0.0.1<\/strong>\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Backup<\/strong><\/p>\n<pre>vrrp_instance <strong>VirtualIP01<\/strong> {\r\n    state <strong>BACKUP<\/strong>\r\n    interface <strong>eth0<\/strong>\r\n    virtual_router_id <strong>999<\/strong>\r\n    priority <strong>90<\/strong>\r\n    advert_int <strong>1<\/strong>\r\n    authentication {\r\n        auth_type PASS\r\n        auth_pass <strong>7bd3a2aa-f49b-11ef-8b04-ff74caed956a<\/strong>\r\n    }\r\n    virtual_ipaddress {\r\n        <strong>10.0.0.1<\/strong>\r\n    }\r\n}<\/pre>\n<p><strong>Configuration<\/strong><\/p>\n<ul>\n<li><strong>VirtualIP01<\/strong> is an arbitrary name for this setup.\n<ul>\n<li>It helps to identify the purpose of the configuration block in the file.<\/li>\n<\/ul>\n<\/li>\n<li><strong>MASTER<\/strong>\/<strong>BACKUP<\/strong> represents their relationship at the initial state.\n<ul>\n<li>Defines who has the authority to decide the active instance.<\/li>\n<\/ul>\n<\/li>\n<li><strong>eth0<\/strong> is the interface name in each instance.\n<ul>\n<li>The interface names identify the hardware and are specific to the instance internals.<\/li>\n<\/ul>\n<\/li>\n<li><strong>999\u00a0<\/strong>is a number that tells each other what virtual address(es) the help check refers to.\n<ul>\n<li>Servers can have multiple relationships for different address(es).<\/li>\n<\/ul>\n<\/li>\n<li><strong>90<\/strong>\/<strong>100\u00a0<\/strong>is the priority set to each instance to define who has the greater to be active.\n<ul>\n<li>In the event of multiple backups, the priority number makes more sense.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Enable the service in all instances.<\/p>\n<pre>sudo systemctl enable keepalived --now\r\nsudo systemctl status keepalived\r\nip -4 -brief a<\/pre>\n<p>For a more refined prioritization taking into consideration the health of NGINX, define the master as follows.<\/p>\n<pre>vrrp_script <strong>Check_NGINX<\/strong> {\r\n    script \"<strong>\/usr\/bin\/pgrep nginx<\/strong>\"\r\n    interval <strong>2<\/strong>\r\n    weight <strong>-30<\/strong>\r\n}\r\n\r\nvrrp_instance <strong>VirtualIP01<\/strong> {\r\n    state <strong>MASTER<\/strong>\r\n    interface <strong>eth0<\/strong>\r\n    virtual_router_id <strong>999<\/strong>\r\n    priority <strong>100<\/strong>\r\n    advert_int <strong>1<\/strong>\r\n    authentication {\r\n        auth_type PASS\r\n        auth_pass <strong>7bd3a2aa-f49b-11ef-8b04-ff74caed956a<\/strong>\r\n    }\r\n    virtual_ipaddress {\r\n        <strong>10.0.0.1<\/strong>\r\n    }\r\n    track_script {\r\n        <strong>Check_NGINX<\/strong>\r\n    }\r\n}<\/pre>\n<p><strong>Note:<\/strong> the script <strong>Check_NGINX<\/strong> will check if NGINX is running every <strong>2<\/strong> seconds. If it fails, the priority of the <strong>MASTER<\/strong> instance will drop by <strong>30<\/strong> (from 100 to 70), and the <strong>BACKUP<\/strong> instance, which has a priority of <strong>90<\/strong>, might take over the virtual IP. It can also be set to check interface status (down\/up) or a running process or manage routes based on status (with <strong>virtual_routes<\/strong>).<\/p>\n<p><strong>Reflections<\/strong><\/p>\n<p>Keep in mind that while the second server is the backup for the first server in one or more IPs, the first server can also be the backup for the second server in other VRRP relationships. Multiple servers can relate to each other in many ways at the same time.<\/p>\n<p>VRRP by default does multicasting, which creates security concerns in a shared broadcast domain (not recommended). The usage of unicast peer(s) does not resolve the issue but gives it a bit more control over the communication. Replace the <strong>X<\/strong> with the IP of the peer instance.<\/p>\n<pre>global_defs {\r\n    enable_script_security\r\n}\r\nvrrp_instance VirtualIP01 {\r\n    (...)\r\n    unicast_src_ip 10.0.0.<strong>Y<\/strong>\r\n    unicast_peer {\r\n        10.0.0.<strong>X<\/strong>\r\n    }\r\n    (...)\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>CARP (Common Address Redundancy Protocol) is an alternative protocol to VRRP (Virtual Router Redundancy Protocol), [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,8],"tags":[],"class_list":["post-622","post","type-post","status-publish","format-standard","hentry","category-ccna","category-pfsense"],"_links":{"self":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/622","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=622"}],"version-history":[{"count":10,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/622\/revisions"}],"predecessor-version":[{"id":4822,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/622\/revisions\/4822"}],"wp:attachment":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}