# How to configure a firewall for SSH and for EPICS

## Firewall configuration for SSH

On the {{host}} and {{target}}(s) computers, make sure that
port 22 (default {{SSH}} port) is open:

* E.g. with [firewalld](https://repology.org/project/firewalld/versions) (for Ferdora, CentOS,
  Rocky Linux, Alma Linux, etc):

    ```{code} bash
    $ sudo firewall-cmd --add-port=22/tcp --permanent
    $ sudo firewall-cmd --reload
    ```

* E.g. with [ufw](https://repology.org/project/ufw/versions) (for Ubuntu, Manjaro, openSUSE,
  Gentoo, etc):

    ```{code} bash
    $ sudo ufw allow 22/tcp
    ```

* Or with [iptables](https://repology.org/project/iptables/versions) (for any distro if
  [firewalld](https://repology.org/project/firewalld/versions) and
  [ufw](https://repology.org/project/ufw/versions) are not available):

    ```{code} bash
    $ sudo iptables -A INPUT -p tcp –-dport 22 -j ACCEPT
    ```

    then restart the `iptables` services, e.g. on `systemd` based distro:

    ```{code} bash
    $ sudo systemctl restart iptables
    ```

---

## Standard firewall configuration for EPICS

### Standard firewall configuration for Channel Access (CA)

* On the {{host}} only, make sure port `5064` and port `5065` (default
  {{CA}} ports) are open:

  * E.g. with [firewalld](https://repology.org/project/firewalld/versions):

      ```{code} bash
      $ sudo firewall-cmd --add-port=5064/tcp --permanent
      $ sudo firewall-cmd --add-port=5064/udp --permanent
      $ sudo firewall-cmd --add-port=5065/udp --permanent
      $ sudo firewall-cmd --add-port=5065/tcp --permanent
      $ sudo firewall-cmd --reload
      ```
  
  * E.g. with [ufw](https://repology.org/project/ufw/versions):

      ```{code} bash
      $ sudo ufw allow 5064/tcp
      $ sudo ufw allow 5064/udp
      $ sudo ufw allow 5065/tcp
      $ sudo ufw allow 5065/udp
      ```
  
  * Or with [iptables](https://repology.org/project/iptables/versions):

      ```{code} bash
      $ sudo iptables -A INPUT -p tcp --dport 5064 -j ACCEPT
      $ sudo iptables -A INPUT -p tcp --sport 5064 -j ACCEPT

      $ sudo iptables -A INPUT -p udp --dport 5064 -j ACCEPT
      $ sudo iptables -A INPUT -p udp --sport 5064 -j ACCEPT

      $ sudo iptables -A INPUT -p tcp --dport 5065 -j ACCEPT
      $ sudo iptables -A INPUT -p tcp --sport 5065 -j ACCEPT

      $ sudo iptables -A INPUT -p udp --dport 5065 -j ACCEPT
      $ sudo iptables -A INPUT -p udp --sport 5065 -j ACCEPT
      ```

      then restart the `iptables` services, e.g. on `systemd` based distro:

      ```{code} bash
      $ sudo systemctl restart iptables
      ```

```{important}
On the {{host}}, if you intend to run more than one {{IOC_program}},\
then *you have to* read
the [TCP ports limitation explanations](../../explanations/tcp_ports_limitation_explanations.md)!\
This is important because in this case,
you will have to open more ports\
(usually an additional TCP port and UDP port per {{IOC_program}})\
and this will have an impact on the {{IOC}}s clients configuration.\
To open additional ports: just repeat the previous step with the desired ports numbers.
```

<!--
❓ NOT NECESSARY❓
* On the {{host}} only, in order to make sure that {{CA}} client
  will unicast only (and not broadcast), set the following {{EPICS}} environment
  variables:

    ```{code} bash
    $ vi ~/.bashrc # or ~/.zshrc or whatever
        > export EPICS_CA_AUTO_ADDR_LIST="NO" # disable auto network introspection, i.e. no broadcast search
        > export EPICS_CA_ADDR_LIST="127.0.0.1:5064" # CA clients only search PVs locally
    
    $ source ~/.bashrc # or ~/.zshrc or whatever
    ```

    ```{tip}
    If the {{host}} has {{CA}} clients that needs to
    reach other {{IOC}}s, then just add those {{IOC}}s' IPs **and
    ports numbers** in `EPICS_CA_AUTO_ADDR_LIST`.
    ```
-->

### Standard firewall configuration for PV Access (PVA)

* On the {{host}} only,
make sure port `5075` and port `5076`
(default {{PVA}} ports)
are open:

  * E.g. with [firewalld](https://repology.org/project/firewalld/versions):

      ```{code} bash
      $ sudo firewall-cmd --add-port=5075/tcp --permanent
      $ sudo firewall-cmd --add-port=5076/udp --permanent
      $ sudo firewall-cmd --reload
      ```
  
  * E.g. with [ufw](https://repology.org/project/ufw/versions):

      ```{code} bash
      $ sudo ufw allow 5075/tcp
      $ sudo ufw allow 5076/udp
      ```
  
  * Or with [iptables](https://repology.org/project/iptables/versions):

      ```{code} bash
      $ sudo iptables -A INPUT -p tcp --dport 5075 -j ACCEPT
      $ sudo iptables -A INPUT -p tcp --sport 5075 -j ACCEPT
      $ sudo iptables -A INPUT -p udp --dport 5076 -j ACCEPT
      $ sudo iptables -A INPUT -p udp --sport 5076 -j ACCEPT
      ```

      then restart the `iptables` services, e.g. on `systemd` based distro:

      ```{code} bash
      $ sudo systemctl restart iptables
      ```

<!--
❓ NECESSARY❓
* On the {{host}} only, make sure that any additional ports (e.g. ports
  specified in [the upcomming "IMPORTANT ports limitations"
  section](../../explanations/tcp_ports_limitation_explanations.md)) are open (just repeat the
  previous step with the desired ports numbers).
-->

---

## Very OPTIONAL paranoid firewall configuration for EPICS

### Paranoid firewall configuration for Channel Access (CA)

If you want to make sure that absolutely no {{CA}} messages can get out of your
{{host}} computer, then apply the following configurations.

```{warning}
If doing this, then you won't be able to access {{host}}
{{PV}}s from another computer (i.e. no monitoring, no archiving, no alarms etc.).
```

* On the {{host}} only, make sure port `5064` and port `5065` (default
  {{CA}} ports) are open **only for localhost**...

  * E.g. with [firewalld](https://repology.org/project/firewalld/versions):

      ```{code} bash
      # firewall-cmd --permanent --new-service=local-ca
      # firewall-cmd --permanent --service=local-ca --set-description="EPICS Channel Access for localhost only"
      # firewall-cmd --permanent --service=local-ca --set-short="EPICS CA for localhost only"
      # firewall-cmd --permanent --service=local-ca --add-protocol=tcp
      # firewall-cmd --permanent --service=local-ca --add-protocol=udp
      # firewall-cmd --permanent --service=local-ca --add-port=5064/tcp
      # firewall-cmd --permanent --service=local-ca --add-port=5065/udp
      # firewall-cmd --permanent --service=local-ca --add-source-port=5064/tcp
      # firewall-cmd --permanent --service=local-ca --add-source-port=5065/udp
      # firewall-cmd --permanent --service=local-ca --set-destination=ipv4:127.0.0.1
      # firewall-cmd --reload

      # firewall-cmd --info-service=local-ca
          > local-ca
          >   ports: 5065/udp 5064/tcp
          >   protocols: tcp udp
          >   source-ports: 5064/tcp 5065/udp
          >   modules:
          >   destination: ipv4:127.0.0.1

      # firewall-cmd --permanent --new-zone=local-epics
      # firewall-cmd --permanent --zone=local-epics --add-source=127.0.0.1
      # firewall-cmd --reload

      # firewall-cmd --get-zones

      # firewall-cmd --permanent --zone=local-epics --add-service=local-ca
      # firewall-cmd --reload

      # firewall-cmd --zone=local-epics --list-services
          > local-ca
      # firewall-cmd --zone=local-epics --query-service=local-ca
          > yes
      ```

  * E.g. with [ufw](https://repology.org/project/ufw/versions):

      ```{code} bash
      # ufw allow tcp from localhost to localhost port 5064
      # ufw allow udp from localhost to localhost port 5065
      ```

  * Or with [iptables](https://repology.org/project/iptables/versions):
      TODO

* On the {{host}}, if you intend to run more than one {{IOC_program}},
  then *you have to* read
  the [TCP ports limitation explanations](../../explanations/tcp_ports_limitation_explanations.md)!
  This is important because in this case,
  you will have to open more ports
  (usually an additional TCP port and UDP port per {{IOC_program}})
  and this will have an impact on the {{IOC}}s clients configuration.
  To open additional ports: just repeat the previous step with the desired ports numbers.

### Paranoid firewall configuration for PV Access (PVA)

If you want to make sure that absolutely no {{PVA}} messages can get out of your
{{host}} computer, then apply the following configurations.

```{warning}
If doing this, then you won't be able to access {{host}}
{{PV}}s from another computer (i.e. no monitoring, no archiving, no alarms etc.).
```

* On the {{host}} only, make sure port `5075` and port `5076` (default
  {{PVA}} ports) are open **only for localhost**...

  * E.g. with [firewalld](https://repology.org/project/firewalld/versions):

      ```{code} bash
      # firewall-cmd --permanent --new-service=local-pva
      # firewall-cmd --permanent --service=local-pva --set-description="EPICS PV Access for localhost only"
      # firewall-cmd --permanent --service=local-cva --set-short="EPICS PVA for localhost only"
      # firewall-cmd --permanent --service=local-cva --add-protocol=tcp
      # firewall-cmd --permanent --service=local-cva --add-protocol=udp
      # firewall-cmd --permanent --service=local-cva --add-port=5075/tcp
      # firewall-cmd --permanent --service=local-cva --add-port=5076/udp
      # firewall-cmd --permanent --service=local-cva --add-source-port=5075/tcp
      # firewall-cmd --permanent --service=local-cva --add-source-port=5076/udp
      # firewall-cmd --permanent --service=local-cva --set-destination=ipv4:127.0.0.1
      # firewall-cmd --reload

      # firewall-cmd --info-service=local-pva
          > local-pva
          >   ports: 5076/udp 5075/tcp
          >   protocols: tcp udp
          >   source-ports: 5075/tcp 5076/udp
          >   modules:
          >   destination: ipv4:127.0.0.1

      # firewall-cmd --permanent --new-zone=local-epics
      # firewall-cmd --permanent --zone=local-epics --add-source=127.0.0.1
      # firewall-cmd --reload

      # firewall-cmd --get-zones

      # firewall-cmd --permanent --zone=local-epics --add-service=local-pva
      # firewall-cmd --reload

      # firewall-cmd --zone=local-epics --list-services
          > local-pva
      # firewall-cmd --zone=local-epics --query-service=local-pva
          > yes
      ```

  * E.g. with [ufw](https://repology.org/project/ufw/versions):

      ```{code} bash
      # ufw allow tcp from localhost to localhost port 5075
      # ufw allow udp from localhost to localhost port 5076
      ```

  * Or with [iptables](https://repology.org/project/iptables/versions):
      TODO

<!--
❓ NECESSARY❓
* On the {{host}} only, make sure that any additional ports (e.g. ports
  specified in [the upcomming "IMPORTANT ports limitations"
  section](../../explanations/tcp_ports_limitation_explanations.md)) are open (just repeat the
  previous step with the desired port number).
-->

---

## Sources

* <web-archive:20220312075228/https://epics-controls.org/resources-and-support/documents/howto-documents/configure-channel-access/>
* <web-archive:20220312075627/https://epics.anl.gov/base/R7-0/6-docs/CAref.html#firewall>
* <web-archive:20220312075627/https://epics.anl.gov/base/R7-0/6-docs/CAref.html#EPICS>
* <web-archive:20220312075627/https://epics.anl.gov/base/R7-0/6-docs/CAref.html#Environmen>
* <web-archive:20220312075853/https://docs.epics-controls.org/en/latest/specs/IOCInit.html?highlight=EPICS_CA_ADDR_LIST#environment-variables>

