├── snmp └── inet.conf ├── options └── inet.conf ├── ssh └── inet.conf ├── ospf ├── README.md ├── inet.conf └── inet6.conf ├── ntp └── inet.conf ├── vrrp ├── inet6.conf └── inet.conf ├── fragments └── inet.conf ├── icmp ├── inet.conf └── inet6.conf ├── LICENSE ├── traceroute-udp └── inet.conf ├── bfd ├── inet.conf └── inet6.conf ├── dhcp ├── README.md └── inet.conf ├── bgp ├── inet.conf └── inet6.conf ├── ldp └── inet.conf ├── rsvp └── inet.conf └── README.md /snmp/inet.conf: -------------------------------------------------------------------------------- 1 | /* SNMP inet 2 | 3 | Purpose: 4 | Allows SNMP packets from the specified clients to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list. 8 | 9 | References: 10 | 11 | Notes: 12 | Destination address can be restricted to loopback or preferred IP for SNMP management. 13 | 14 | */ 15 | 16 | 17 | term snmp:inet:in { 18 | from { 19 | source-address snmp-hosts-v4; 20 | destination-address snmp-local-v4; 21 | protocol udp; 22 | destination-port 161; 23 | } 24 | then { 25 | count snmp:inet:in; 26 | accept; 27 | } 28 | } -------------------------------------------------------------------------------- /options/inet.conf: -------------------------------------------------------------------------------- 1 | /* Options inet 2 | 3 | Purpose: 4 | Discard IP Options that should not be seen by this router 5 | 6 | Application: 7 | As an first input filter term or as first part of an input-list 8 | 9 | References: 10 | RFC6398 - IP Router Alert Considerations and Usage 11 | - https://datatracker.ietf.org/doc/html/rfc6398 12 | 13 | Notes: 14 | Decide if your router needs to process IP Options packets or not. 15 | Router-alert is used by RSVP and ISMP, MLD, MRD and GIST. 16 | 17 | */ 18 | 19 | 20 | term options:inet:in { 21 | from { 22 | ip-options any; 23 | } 24 | then { 25 | count options:inet:in; 26 | discard; 27 | } 28 | } -------------------------------------------------------------------------------- /ssh/inet.conf: -------------------------------------------------------------------------------- 1 | /* SSH inet 2 | 3 | Purpose: 4 | Allows SSH connections from the specified hosts to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC4253 - Secure Shell 11 | - https://datatracker.ietf.org/doc/html/rfc4253 12 | 13 | Notes: 14 | Destination address can be restricted to loopback or preferred IP for management. 15 | 16 | */ 17 | 18 | 19 | term ssh:inet:in { 20 | from { 21 | source-address management-hosts-v4; 22 | destination-address ssh-local-v4; 23 | protocol tcp; 24 | destination-port 22; 25 | } 26 | then { 27 | count ssh:inet:in; 28 | accept; 29 | } 30 | } -------------------------------------------------------------------------------- /ospf/README.md: -------------------------------------------------------------------------------- 1 | # OSPF 2 | 3 | ## General Notes 4 | If you are using OSPF in your network, understand the use case 5 | * Will your network only use OSPF point-to-point links? 6 | * Do you need to use broadcast segments and therefore accommodate DR/BDR election? 7 | 8 | In the case of a network exclusively using point-to-point links, the destination will always be 224.0.0.5 (AllSPFRouters), according to [RFC2328](https://www.rfc-editor.org/rfc/rfc2328): 9 | 10 | >"The IP destination address for the packet is selected as 11 | >follows. On physical point-to-point networks, the IP 12 | >destination is always set to the address AllSPFRouters." 13 | 14 | Therefore the filter can be restricted to only allow this destination address. This will significantly reduce the available attack surface by elimintating any unicast destinations. 15 | -------------------------------------------------------------------------------- /ntp/inet.conf: -------------------------------------------------------------------------------- 1 | /* NTP inet 2 | 3 | Purpose: 4 | Allows NTP from the specified hosts to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list. 8 | 9 | References: 10 | RFC5905 - NTPv4 11 | - https://datatracker.ietf.org/doc/html/rfc5905 12 | 13 | Notes: 14 | Destination address can be restricted to loopback or preferred update-source. 15 | JunOS likes to use fxp0 or equivalent for show ntp associations, so this can break that functionality. 16 | 17 | */ 18 | 19 | 20 | term ntp:inet:in { 21 | from { 22 | source-address ntp-servers-v4; 23 | destination-address ntp-local-v4; 24 | protocol udp; 25 | destination-port 123; 26 | } 27 | then { 28 | count ntp:inet:in; 29 | accept; 30 | } 31 | } -------------------------------------------------------------------------------- /vrrp/inet6.conf: -------------------------------------------------------------------------------- 1 | /* VRRP inet6 2 | 3 | Purpose: 4 | Allows VRRP Multicast from the specified sources to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC5798 - VRRPv3 11 | - https://datatracker.ietf.org/doc/html/rfc5798 12 | 13 | Notes: 14 | Adjust sources as required. 15 | 16 | */ 17 | 18 | 19 | term vrrp:inet6:in { 20 | from { 21 | next-header vrrp; 22 | hop-limit 255; 23 | source-address { 24 | /* VRRP IPv6 peer addresses participating in the group */ 25 | FE80::/64; 26 | } 27 | destination-address { 28 | /* VRRP local IPv6 address */ 29 | FF02::12/128; 30 | } 31 | } 32 | then { 33 | count vrrp:inet6:in; 34 | accept; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fragments/inet.conf: -------------------------------------------------------------------------------- 1 | /* Fragments inet 2 | 3 | Purpose: 4 | Discard fragments that should never be seen by this router 5 | 6 | Application: 7 | As an first input filter term or as first part of an input-list 8 | 9 | References: 10 | RFC1858 - Fragment Filtering 11 | - https://datatracker.ietf.org/doc/html/rfc1858 12 | RFC3128 - Protection Against Tiny Fragment Attack 13 | - https://datatracker.ietf.org/doc/html/rfc3128 14 | 15 | Notes: 16 | Decide if your router needs to process fragments or not. 17 | 18 | */ 19 | 20 | 21 | term fragments:inet:first { 22 | from { 23 | first-fragment; 24 | } 25 | then { 26 | count fragments:inet:first; 27 | discard; 28 | } 29 | } 30 | term fragments:inet:fragment { 31 | from { 32 | is-fragment; 33 | } 34 | then { 35 | count fragments:inet:fragment; 36 | discard; 37 | } 38 | } -------------------------------------------------------------------------------- /icmp/inet.conf: -------------------------------------------------------------------------------- 1 | /* ICMP inet 2 | 3 | Purpose: 4 | Allows operationally required ICMPv4 packets to this router 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0 8 | 9 | References: 10 | RFC1812 - Requirements for IPv4 Routers 11 | - https://datatracker.ietf.org/doc/html/rfc1812 12 | RFC6633 - Deprecation of Source Quench 13 | - https://datatracker.ietf.org/doc/html/rfc6633 14 | 15 | Notes: 16 | JunOS does not send router advertisements by default. 17 | Routers should not normally need to receive these either. 18 | ICMP Parameter Problem should not be needed inbound. 19 | Source Quench messages are deprecated. 20 | 21 | */ 22 | 23 | 24 | term icmp:inet:in { 25 | from { 26 | protocol icmp; 27 | icmp-type [ echo-reply echo-request time-exceeded unreachable ]; 28 | } 29 | then { 30 | count icmp:inet:in; 31 | accept; 32 | } 33 | } -------------------------------------------------------------------------------- /ospf/inet.conf: -------------------------------------------------------------------------------- 1 | /* OSPFv2 inet 2 | 3 | Purpose: 4 | Allows OSPFv2 from the specified sources to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC2328 - OSPFv2 11 | - https://datatracker.ietf.org/doc/html/rfc2328 12 | 13 | Notes: 14 | Adjust destination addresses to suit your implementation. 15 | On a router with only p2p links destination 224.0.0.5 will be enough. 16 | TTL = 1 should be safe in a Juniper network. 17 | 18 | */ 19 | 20 | 21 | term ospf:inet:in { 22 | from { 23 | protocol ospf; 24 | ttl 1; 25 | source-address ospf-neighbors-v4; 26 | destination-address { 27 | /* IPv4 Local OSPF Addresses */ 28 | 224.0.0.5/32; 29 | 224.0.0.6/32; 30 | } 31 | } 32 | then { 33 | count ospf:inet:in; 34 | accept; 35 | } 36 | } -------------------------------------------------------------------------------- /vrrp/inet.conf: -------------------------------------------------------------------------------- 1 | /* VRRP inet 2 | 3 | Purpose: 4 | Allows VRRP Multicast from the specified sources to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC5798 - VRRPv3 11 | - https://datatracker.ietf.org/doc/html/rfc5798 12 | RFC2338 - VRRP (Authentication) 13 | - https://datatracker.ietf.org/doc/html/rfc2338 14 | 15 | Notes: 16 | VRRP authentication is still available in JunOS but not recommended. 17 | Authentication will not prevent a hostile node becoming master. 18 | 19 | */ 20 | 21 | 22 | term vrrp:inet:in { 23 | from { 24 | protocol vrrp; 25 | ttl 255; 26 | source-address vrrp-peers-v4; 27 | destination-address { 28 | /* VRRP Local IPv4 Address */ 29 | 224.0.0.18/32; 30 | } 31 | } 32 | then { 33 | count vrrp:inet:in; 34 | accept; 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 lpedder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ospf/inet6.conf: -------------------------------------------------------------------------------- 1 | /* OSPFv3 inet6 2 | 3 | Purpose: 4 | Allows OSPFv3 from the specified sources to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC5340 - OSPFv3 11 | - https://datatracker.ietf.org/doc/html/rfc5340 12 | 13 | Notes: 14 | Adjust destination addresses to suit your implementation. 15 | On a router with only p2p links destination FF02::5 will be enough. 16 | Hop-Limit = 1 should be safe in a Juniper network. 17 | 18 | */ 19 | 20 | 21 | term ospf:inet6:in { 22 | from { 23 | next-header ospf; 24 | hop-limit 1; 25 | source-address { 26 | /* IPv6 OSPF Neighbor Addresses - Should always be link-local */ 27 | FE80::/64; 28 | } 29 | destination-address { 30 | /* IPv6 Local OSPF Addresses */ 31 | FF02::5/128; 32 | FF02::6/128; 33 | FE80::/64; 34 | } 35 | } 36 | then { 37 | count ospf:inet6:in; 38 | accept; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /icmp/inet6.conf: -------------------------------------------------------------------------------- 1 | /* ICMP inet6 2 | 3 | Purpose: 4 | Allows ICMPv6 Neighbor Discovery packets to this router 5 | Allows operationally required ICMPv6 packets to this router 6 | 7 | Application: 8 | As an input filter term or as part of an input-list on lo0 9 | 10 | References: 11 | RFC4861 - Neighbor Discovery 12 | - https://datatracker.ietf.org/doc/html/rfc4861 13 | RFC9099 - IPv6 OPSec 14 | - https://datatracker.ietf.org/doc/html/rfc9099 15 | 16 | Notes: 17 | Parameter Problem should not be required 18 | 19 | */ 20 | 21 | 22 | term icmp:inet6:nd-in { 23 | from { 24 | next-header icmp6; 25 | icmp-type [ router-solicit router-advertisement neighbor-solicit neighbor-advertisement ]; 26 | hop-limit 255; 27 | } 28 | then { 29 | count icmp:inet6:nd-in; 30 | accept; 31 | } 32 | } 33 | term icmp:inet6:in { 34 | from { 35 | next-header icmp6; 36 | icmp-type [ echo-reply echo-request time-exceeded destination-unreachable packet-too-big ]; 37 | } 38 | then { 39 | count icmp:inet6:in; 40 | accept; 41 | } 42 | } -------------------------------------------------------------------------------- /traceroute-udp/inet.conf: -------------------------------------------------------------------------------- 1 | /* Traceroute inet 2 | 3 | Purpose: 4 | Allows *nix style UDP traceroute packets to this router. 5 | The router responds with an ICMP port unreachable message. 6 | 7 | Application: 8 | As an input filter term or as part of an input-list on lo0. 9 | 10 | References: 11 | RFC1812 - Requirements for IPv4 Routers 12 | - https://datatracker.ietf.org/doc/html/rfc1812 13 | traceroute(8) - Linux manpage for traceroute(8) 14 | - https://man7.org/linux/man-pages/man8/traceroute.8.html 15 | 16 | Notes: 17 | Decide if you want to allow this. It exposes UDP ports and path to the control-plane. 18 | Not allowing this will prevent the last hop of traceroutes completing where this device is the destination. This may not be essential. 19 | ICMP traceroutes are already handled by time-exceeded notifications. 20 | 21 | */ 22 | 23 | 24 | term traceroute-udp:inet:in { 25 | from { 26 | destination-address traceroute-local-v4; 27 | protocol udp; 28 | ttl 1; 29 | destination-port 33435-33450; 30 | } 31 | then { 32 | count traceroute-udp:inet:in; 33 | accept; 34 | } 35 | } -------------------------------------------------------------------------------- /bfd/inet.conf: -------------------------------------------------------------------------------- 1 | /* BFD inet 2 | 3 | Purpose: 4 | Allows BFD control packets to this router for single and multi-hop sessions 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0 8 | 9 | References: 10 | RFC5880 - Bidirectional Forwarding Detection 11 | - https://datatracker.ietf.org/doc/html/rfc5880 12 | RFC5881 - Bidirectional Forwarding Detection (Single Hop) 13 | - https://datatracker.ietf.org/doc/html/rfc5881 14 | RFC5883 - Bidirectional Forwarding Detection (Multi Hop) 15 | - https://datatracker.ietf.org/doc/html/rfc5883 16 | Juniper - JunOS - Supported BFD Standards 17 | - https://www.juniper.net/documentation/us/en/software/junos/standards/topics/concept/bfd.html 18 | 19 | Notes: 20 | JunOS does not support BFD echo or demand mode as per RFC5880. 21 | 22 | */ 23 | 24 | 25 | term bfd:inet:sh-in { 26 | from { 27 | source-address bfd-sh-peers-v4; 28 | destination-address bfd-sh-local-v4; 29 | protocol udp; 30 | source-port 49152-65535; 31 | destination-port 3784; 32 | ttl 255; 33 | } 34 | then { 35 | count bfd:inet:sh-in; 36 | accept; 37 | } 38 | } 39 | term bfd:inet:mh-in { 40 | from { 41 | source-address bfd-mh-peers-v4; 42 | destination-address bfd-mh-local-v4; 43 | protocol udp; 44 | source-port 49152-65535; 45 | destination-port 4784; 46 | } 47 | then { 48 | count bfd:inet:mh-in; 49 | accept; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /bfd/inet6.conf: -------------------------------------------------------------------------------- 1 | /* BFD inet6 2 | 3 | Purpose: 4 | Allows BFD control packets to this router for single and multi-hop sessions 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0 8 | 9 | References: 10 | RFC5880 - Bidirectional Forwarding Detection 11 | - https://datatracker.ietf.org/doc/html/rfc5880 12 | RFC5881 - Bidirectional Forwarding Detection (Single Hop) 13 | - https://datatracker.ietf.org/doc/html/rfc5881 14 | RFC5883 - Bidirectional Forwarding Detection (Multi Hop) 15 | - https://datatracker.ietf.org/doc/html/rfc5883 16 | Juniper - JunOS - Supported BFD Standards 17 | - https://www.juniper.net/documentation/us/en/software/junos/standards/topics/concept/bfd.html 18 | 19 | Notes: 20 | JunOS does not support BFD echo or demand mode as per RFC5880. 21 | 22 | */ 23 | 24 | 25 | term bfd:inet6:sh-in { 26 | from { 27 | source-address bfd-sh-peers-v6; 28 | destination-address bfd-sh-local-v6; 29 | next-header udp; 30 | source-port 49152-65535; 31 | destination-port 3784; 32 | hop-limit 255; 33 | } 34 | then { 35 | count bfd:inet6:sh-in; 36 | accept; 37 | } 38 | } 39 | term bfd:inet6:mh-in { 40 | from { 41 | source-address bfd-mh-peers-v6; 42 | destination-address bfd-mh-local-v6; 43 | next-header udp; 44 | source-port 49152-65535; 45 | destination-port 4784; 46 | } 47 | then { 48 | count bfd:inet6:mh-in; 49 | accept; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /dhcp/README.md: -------------------------------------------------------------------------------- 1 | # DHCP 2 | 3 | ## General Notes 4 | DHCP on JunOS is not a very nice protocol to protect. According to the Juniper [documentation](https://www.juniper.net/documentation/us/en/software/junos/routing-policy/topics/example/subscriber-management-dhcp-firewall-filter.html) there are a couple of things going on: 5 | 6 | * When an FPC receives any DHCP packet, it will change both source and destination ports to 68. 7 | A 8 | * These packets are re-encapsulated in new UDP headers by jdhcpd and sent to the RE 9 | 10 | Therefore, firewall filters matching DHCP packets need to cater for ports seen by the FPCs *and* the REs. 11 | 12 | There is also something unusual going on with DHCP relay. When the RE relays a request to a DHCP server, the source and destination ports leaving the RE are both 67. The DHCP server will reply with the same ports. When this reply arrives on the FPCs, it is again translated to 68 for both source and destination port. Therefore both ports must be allowed in these filters. 13 | 14 | Additionally, Juniper [states](https://www.juniper.net/documentation/us/en/software/junos/dhcp/topics/topic-map/dhcp-relay-agent-security-devices.html) that: 15 | 16 | >After establishing the initial lease on the IP address, the DHCP client and the DHCP server use unicast transmission to negotiate lease renewal or release. The DHCP relay agent “snoops” on all of the packets unicast between the client and the server that pass through the router (or switch) to determine when the lease for this client has expired or been released. This process is referred to as lease shadowing or passive snooping. 17 | 18 | In general, only use this filter if you know you are using DHCP or DHCP relay. The filter should be monitored to ensure terms are being correctly matched. 19 | -------------------------------------------------------------------------------- /dhcp/inet.conf: -------------------------------------------------------------------------------- 1 | /* DHCP inet 2 | 3 | Purpose: 4 | Allows DHCP client and relay from the specified sources to this router. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC2131 - DHCPv4 11 | - https://datatracker.ietf.org/doc/html/rfc2131 12 | RFC3046 - DHCP Relay Agent Information Option 13 | - https://datatracker.ietf.org/doc/html/rfc3046 14 | Juniper - JunOS - Configuring a DHCP Firewall Filter to Protect the Routing Engine 15 | - https://www.juniper.net/documentation/us/en/software/junos/routing-policy/topics/example/subscriber-management-dhcp-firewall-filter.html 16 | 17 | Notes: 18 | Juniper jdhcpd re-encapsulates DHCP packets from FPC to RE changing src/dst port to 68. 19 | Juniper DHCP relay uses port src/dst port 67 when forwarding to the server. 20 | Therefore, in most cases, both ports must be permitted. 21 | The DHCP relay agent snoops on all unicast packets between the client and the server. 22 | 23 | */ 24 | 25 | 26 | term dhcp:inet:client-in { 27 | from { 28 | protocol udp; 29 | source-port 68; 30 | destination-port [ 67 68 ]; 31 | destination-address { 32 | /* DHCP Client Destinations - Include Broadcast and Server Unicast IPv4 */ 33 | 255.255.255.255/32; 34 | } 35 | } 36 | then { 37 | count dhcp:inet:client-in; 38 | accept; 39 | } 40 | } 41 | term dhcp:inet:relay-server-in { 42 | from { 43 | protocol udp; 44 | source-port [ 67 68 ]; 45 | destination-port [ 67 68 ]; 46 | source-address dhcp-relay-servers-v4; 47 | } 48 | then { 49 | count dhcp:inet:relay-server-in; 50 | accept; 51 | } 52 | } -------------------------------------------------------------------------------- /bgp/inet.conf: -------------------------------------------------------------------------------- 1 | /* BGPv4 inet 2 | 3 | Purpose: 4 | Allows BGP connections from the specified peers to this router. 5 | Allows BGP connections from this router to the specified peers. 6 | Facilitates BGP connections using GTSM. 7 | 8 | Application: 9 | As an input filter term or as part of an input-list on lo0 10 | 11 | References: 12 | RFC4271 - BGPv4 13 | - https://datatracker.ietf.org/doc/html/rfc4271 14 | RFC5082 - GTSM 15 | - https://datatracker.ietf.org/doc/html/rfc5082 16 | RFC6056 - Ephemeral Ports 17 | - https://datatracker.ietf.org/doc/html/rfc6056 18 | 19 | Notes: 20 | Juniper uses ephemeral port range 49152-65535 21 | 22 | */ 23 | 24 | 25 | term bgp:inet:gtsm-in { 26 | from { 27 | destination-port 179; 28 | protocol tcp; 29 | source-address bgp-peers-gtsm-v4; 30 | ttl 255; 31 | } 32 | then { 33 | count bgp:inet:gtsm-in; 34 | accept; 35 | } 36 | } 37 | term bgp:inet:gtsm-out { 38 | from { 39 | destination-port 49152-65535; 40 | protocol tcp; 41 | source-address bgp-peers-gtsm-v4; 42 | source-port 179; 43 | ttl 255; 44 | } 45 | then { 46 | count bgp:inet:gtsm-out; 47 | accept; 48 | } 49 | } 50 | term bgp:inet:in { 51 | from { 52 | destination-port 179; 53 | protocol tcp; 54 | source-address bgp-peers-v4; 55 | } 56 | then { 57 | count bgp:inet:in; 58 | accept; 59 | } 60 | } 61 | term bgp:inet:out { 62 | from { 63 | destination-port 49152-65535; 64 | protocol tcp; 65 | source-address bgp-peers-v4; 66 | source-port 179; 67 | } 68 | then { 69 | count bgp:inet:out; 70 | accept; 71 | } 72 | } -------------------------------------------------------------------------------- /ldp/inet.conf: -------------------------------------------------------------------------------- 1 | /* LDP inet 2 | 3 | Purpose: 4 | Allows LDP packets to this router for regular and targeted sessions. 5 | 6 | Application: 7 | As an input filter term or as part of an input-list on lo0. 8 | 9 | References: 10 | RFC5036 - LDP 11 | - https://datatracker.ietf.org/doc/html/rfc5036 12 | 13 | Notes: 14 | JunOS sends LDP hellos from local interface addresses to AllRouters multicast. 15 | LDP sessions are usually established between loopback IPs. 16 | 17 | */ 18 | 19 | 20 | term ldp:inet:hello { 21 | from { 22 | protocol udp; 23 | destination-port 646; 24 | ttl 1; 25 | source-address ldp-neighbors-v4; 26 | destination-address 224.0.0.2/32; 27 | } 28 | then { 29 | count ldp:inet:hello; 30 | accept; 31 | } 32 | } 33 | term ldp:inet:session-in { 34 | from { 35 | protocol tcp; 36 | destination-port 646; 37 | source-address ldp-neighbor-loopbacks-v4; 38 | destination-address ldp-interfaces-v4; 39 | } 40 | then { 41 | count ldp:inet:session-in; 42 | accept; 43 | } 44 | } 45 | term ldp:inet:session-out { 46 | from { 47 | protocol tcp; 48 | source-port 646; 49 | destination-port 49152-65535; 50 | source-address ldp-neighbor-loopbacks-v4; 51 | destination-address ldp-interfaces-v4; 52 | } 53 | then { 54 | count ldp:inet:session-out; 55 | accept; 56 | } 57 | } 58 | term ldp:inet:targeted-hello { 59 | from { 60 | protocol udp; 61 | destination-port 646; 62 | source-address ldp-targeted-peers-v4; 63 | destination-address ldp-targeted-interfaces-v4; 64 | } 65 | then { 66 | count ldp:inet:targeted-hello; 67 | accept; 68 | } 69 | } -------------------------------------------------------------------------------- /bgp/inet6.conf: -------------------------------------------------------------------------------- 1 | /* BGPv4 inet6 2 | 3 | Purpose: 4 | Allows BGP connections from the specified peers to this router. 5 | Allows BGP connections from this router to the specified peers. 6 | Facilitates BGP connections using GTSM. 7 | 8 | Application: 9 | As an input filter term or as part of an input-list on lo0 10 | 11 | References: 12 | RFC4271 - BGPv4 13 | - https://datatracker.ietf.org/doc/html/rfc4271 14 | RFC5082 - GTSM 15 | - https://datatracker.ietf.org/doc/html/rfc5082 16 | RFC6056 - Ephemeral Ports 17 | - https://datatracker.ietf.org/doc/html/rfc6056 18 | 19 | Notes: 20 | Juniper uses ephemeral port range 49152-65535 21 | 22 | */ 23 | 24 | 25 | term bgp:inet6:gtsm-in { 26 | from { 27 | destination-port 179; 28 | next-header tcp; 29 | source-address bgp-peers-gtsm-v6; 30 | hop-limit 255; 31 | } 32 | then { 33 | count bgp:inet6:gtsm-in; 34 | accept; 35 | } 36 | } 37 | term bgp:inet6:gtsm-out { 38 | from { 39 | destination-port 49152-65535; 40 | next-header tcp; 41 | source-address bgp-peers-gtsm-v6; 42 | source-port 179; 43 | hop-limit 255; 44 | } 45 | then { 46 | count bgp:inet6:gtsm-out; 47 | accept; 48 | } 49 | } 50 | term bgp:inet6:in { 51 | from { 52 | destination-port 179; 53 | next-header tcp; 54 | source-address bgp-peers-v6; 55 | } 56 | then { 57 | count bgp:inet6:in; 58 | accept; 59 | } 60 | } 61 | term bgp:inet6:out { 62 | from { 63 | destination-port 49152-65535; 64 | next-header tcp; 65 | source-address bgp-peers-v6; 66 | source-port 179; 67 | } 68 | then { 69 | count bgp:inet6:out; 70 | accept; 71 | } 72 | } -------------------------------------------------------------------------------- /rsvp/inet.conf: -------------------------------------------------------------------------------- 1 | /* RSVP inet 2 | 3 | Purpose: 4 | Allows RSVP messages from the specified neigbors and PEs to and through this router. 5 | Allows RSVP self-ping messages to this router. 6 | 7 | Application: 8 | As an input filter term or as part of an input-list on lo0. 9 | 10 | References: 11 | RFC3209 - RSVP-TE: Extensions to RSVP for LSP Tunnels 12 | - https://datatracker.ietf.org/doc/html/rfc3209 13 | RFC7746 - LSP Self Ping 14 | - https://datatracker.ietf.org/doc/html/rfc7746 15 | RFC6398 - IP Router Alert Considerations and Usage 16 | - https://datatracker.ietf.org/doc/html/rfc6398 17 | RFC2961 - RSVP Refresh Overhead Reduction Extensions 18 | - https://datatracker.ietf.org/doc/html/rfc2961 19 | Juniper - JunOS - RSVP Refresh Reduction 20 | - https://www.juniper.net/documentation/us/en/software/junos/mpls/topics/ref/statement/aggregate-edit-protocols-rsvp.html 21 | 22 | Notes: 23 | RSVP MAY use router alert to send to RE when signalling transit LSPs. 24 | With Router Alert, IP destinations may not be the local router, but remote PEs. 25 | Juniper enables RFC2961 so bundled messages are used by default on JunOS > 15.2. 26 | Router alert flag is not allowed in bundled messages which are sent directly to RSVP neighbors. 27 | Juniper goes against RFC7746 for Self Ping and uses source port 8503, instead of 49152-65535. 28 | 29 | */ 30 | 31 | 32 | term rsvp:inet:in { 33 | from { 34 | protocol rsvp; 35 | source-address rsvp-neighbors-v4; 36 | destination-address rsvp-interfaces-v4; 37 | } 38 | then { 39 | count rsvp:inet:in; 40 | accept; 41 | } 42 | } 43 | term rsvp:inet:self-ping { 44 | from { 45 | protocol udp; 46 | source-port 8503; 47 | destination-port 8503; 48 | source-address rsvp-interfaces-v4; 49 | destination-address loopack-v4; 50 | } 51 | then { 52 | count rsvp:inet:self-ping; 53 | accept; 54 | } 55 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JunOS Filter Elements 2 | Junos Filter Elements by Protocol 3 | 4 | These filter elements aim to provide RFC-referenced and compliant filtering. They would typically be used to build a Routing Engine (RE) Filter and be applied inbound on the lo0 interface. They use the principle of least privilege e.g. the filter elements are as specific as possible 5 | 6 | Feedback and corrections welcome, please submit a pull request or open an issue to discuss 7 | 8 | ## Things to decide First 9 | When constucting a loopback filter there are two questions that need to be answered first: 10 | * Will your router need to process IP Options? 11 | * Will your router need to process fragments? 12 | 13 | These packets are punted to the RE and a possible attack vector. If you don't need these packets on your router, discard them first. 14 | 15 | ### IP Options 16 | 17 | If your network runs RSVP on an older version of JunOS <15.2 (or uses multiple vendors) then perhaps it relies upon the IP Options Router Alert bit. Upon receipt of an packet with this bit set, the router will punt it to the RE, opening a possible attack vector. If you run RSVP the chances are it now uses RFC2961 refresh reduction which prohibits the use of the Router Alert bit in bundled messages. 18 | 19 | If you are sure your network does not need IP Options processing, then deal with this first. 20 | * [Discard Term for IPv4 Options](options/inet.conf) 21 | 22 | ### Fragments 23 | 24 | In a properly dimensioned network, fragmentation should not occur to the router control plane. 25 | 26 | In IPv4, the first-fragment is easily identified: 27 | * More Fragments bit set to 1 28 | * Fragment Offset field set to 0 29 | 30 | If you are not doing fragment processing, then there is no point in completing further layer 3/4 matches on this packet. It needs to go, and accepting it will only take up reassembly buffer space. It should be immediately dropped. 31 | 32 | Subsequent IPv4 Fragments will have: 33 | * Fragment Offset field non-zero 34 | 35 | Because the RE filters are simply bitwise matching on the packet header, there is a theoretical possibility subsequent fragment payloads could match a firewall filter term. So to be absolutely sure, any packet with a non-zero fragment offset should be immediately discarded before further terms are evaluated. 36 | 37 | * [Discard Term for IPv4 Fragments](fragments/inet.conf) 38 | 39 | With IPv6, because all fragments are placed in fragment headers, they can be identified easily: 40 | * next-header value set to fragment (44). 41 | 42 | For IPv6 RE filtering, it is safer to accept on next-header. The next-header match cannot be bypassed and typically everything else gets dropped at the final term. So if you have a long list of next-header accept terms and a discard term at the end, IPv6 fragments will be safely dropped here. 43 | 44 | ## General Approach 45 | 46 | Creating RE filters is by no means easy. They are *stateless* filters which can be a challenge for engineers used to working with stateful firewall policies. This task requires 47 | * Understanding to *packet level* of protocols in use on the network 48 | * Knowledge of all network addressing 49 | * Knowledge of how edge filtering must work in conjunction with RE filters for effective protection 50 | 51 | There are some common pitfalls, so the general approach taken here in building the elements is detailed here. 52 | 53 | ### Use of Prefix-Lists and Apply-Paths 54 | When constructing a firewall filter it can quickly get complex. If you use abstraction to multiple levels this can make it more difficult to read. For this reason, the examples here don't refer to prefix lists or other filters. This makes what is allowed for each protocol clearer. There are other problems with using prefix lists: 55 | * The temptation to re-use them can mean your filters aren't as specific as they could be 56 | * Using JunOS apply-path wildcards in prefix lists can open your filter much wider than you expect 57 | 58 | In the case of a commonly used apply-path wildcard such as this: 59 | ``` 60 | prefix-list router-ipv4 { 61 | apply-path "interfaces <*> unit <*> family inet address <*>"; 62 | } 63 | ``` 64 | You might think that the result will be the /32 addresses of each interface. But this actually takes the full subnet of the interfaces as you can see below: 65 | ``` 66 | user@router> show configuration policy-options prefix-list router-ipv4 | display inheritance 67 | ## 68 | ## apply-path was expanded to: 69 | ## 172.16.24.0/27; 70 | ## 172.16.24.128/29; 71 | ## 203.0.113.0/24; 72 | ## 73 | apply-path "interfaces <*> unit <*> family inet address <*>"; 74 | ``` 75 | This can be danegerous if you are connected to a large peering LAN for example. All the peers would potentially be permitted by your filters referring to this prefix-list! 76 | 77 | Better to know exactly what you are permitting and where you are permitting it from. This is particularly true when using GTSM on BGP peers, which relies on correct filtering based on TTL values. 78 | 79 | ### Always Match Source IPs 80 | 81 | There are only two things that should normally be permitted to the router from anywhere: 82 | * ICMP for essential operations 83 | * Traceroute (UDP unix-style) 84 | 85 | Everything else should be matched on source IPs. 86 | 87 | ### Never Match on Port 88 | 89 | When it comes to matching port numbers, JunOS allows you use three match conditions: 90 | * **port** - Which matches on either source or destination port 91 | * **source-port** - Matches only the source port 92 | * **destination-port** - Matches only the destination port 93 | 94 | A common pitfall is to match only using **port**. The problem here is best explained with an example. In the following filter term: 95 | ``` 96 | term accept-bgp { 97 | from { 98 | source-address { 99 | 198.51.0.1/32; 100 | } 101 | protocol tcp; 102 | port bgp; 103 | } 104 | then { 105 | count accept-bgp; 106 | accept; 107 | } 108 | } 109 | ``` 110 | The remote BGP peer 198.51.0.1 would be able to establish a TCP connection to this router on any destination port simply by setting the source port to 179. This would allow access to port 22 (SSH) for example, exposing a potential attack surface. 111 | 112 | For BGP, the filter should be two terms. Each term matches for one direction as either end can initiate a BGP session. You can see this in the elements provided below. 113 | 114 | ### Also Match on Destination IP If Possible 115 | 116 | Following the principle of least privilege, if there is a way to further restrict a filter term to a known destination IP then it should be used. This is particularly important if your network uses L3VPNs. Because VPN customers may be using the same source IP addresses you have permitted, the destination address should also be matched on a filter term. 117 | 118 | ### Restrict TTLs Where Specified in RFCs 119 | 120 | If an RFC states a protocol MUST set a TTL or hop-limit value for a packet type, then this can help to further limit access in a filter term. For example in IPv6 Neighbor Discovery, the hop-limit value is set to 255. This should be matched in the filter term for ND packets. 121 | 122 | ## Protocols 123 | Here are individual filter elements for each protocol, with references provided to RFCs and documentation. Some protocols have a specific README file that explains the rationale. 124 | 125 | * [BGP](bgp) 126 | * [OSPF](ospf) 127 | * [VRRP](vrrp) 128 | * [ICMP](icmp) 129 | * [RSVP](rsvp) 130 | * [LDP](ldp) 131 | * [BFD](bfd) 132 | 133 | ## Management Protocols 134 | Individual filter elements for each management protocol 135 | 136 | * [SSH](ssh) 137 | * [SNMP](snmp) 138 | * [NTP](ntp) 139 | * [Traceroute](traceroute) 140 | --------------------------------------------------------------------------------