Use the ttl-security Script to Turn on TTL-based Security
For SLAX version 1.0 and higher, you can use the ttl-security script as an easy mechanism to turn on TTL-based security (GTSM).
For example, create an lo0 filter based on your BGP configuration. List any members of BGP groups with "apply-macro ttl-security" turned on in the "ttl-security" filter, and are only allowed if the TTL on incoming packets is 254 (meaning they are exactly one hop away).
Script Implementation
There are three parts to this script:
- First, set the TTL to 255.
- Create a filter that discards traffic where TTL != 254.
- Place that filter in lo0.
You don't want to interfere with an existing filter on lo0, so look at the current state:
- If there's no filter, make one and put a "then accept" on it.
- If there's a single filter, turn it into a filter list with your newly created filter at the front of the list.
- If there's already a filter list, add your new filter to the front of the list.
Source Code and GitHub Links
The source code below is also available from the following GitHub locations:
Example Configuration
01 system {
02 scripts {
03 commit {
04 allow-transients;
05 file ttl-security.slax;
06 }
07 }
08 }
09 protocols {
10 bgp {
11 group test {
12 apply-macro ttl-security;
13 neighbor 10.1.2.3;
14 neighbor 10.3.4.5;
15 neighbor 10.5.6.7;
16 }
17 }
18 }
Example Output
01 system {
02 scripts {
03 commit {
04 allow-transients;
05 file ttl-security.slax;
06 }
07 }
08 }
09 interfaces {
10 lo0 {
11 unit 0 {
12 family inet {
13 filter {
14 input ttl-security;
15 }
16 }
17 }
18 }
19 }
20 protocols {
21 bgp {
22 group test {
23 apply-macro ttl-security;
24 ttl 255;
25 neighbor 10.1.2.3;
26 neighbor 10.3.4.5;
27 neighbor 10.5.6.7;
28 }
29 }
30 }
31 firewall {
32 filter ttl-security {
33 term gtsm {
34 from {
35 source-address {
36 10.1.2.3/32;
37 10.3.4.5/32;
38 10.5.6.7/32;
39 }
40 protocol tcp;
41 ttl-except 254;
42 port 179;
43 }
44 then {
45 discard;
46 }
47 }
48 term else {
49 then {
50 accept;
51 }
52 }
53 }
54 }
SLAX Script Contents
001 version 1.0;
002
003 ns junos = "http://xml.juniper.net/junos/*/junos";
004 ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
005 ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
006
007 import "../import/junos.xsl";
008
009 /*
010 * Implement GTSM for JUNOS
011 *
012 * We need to make an lo0 filter based on our BGP config. Any
013 * members of BGP groups with "apply-macro ttl-security" turned
014 * on are listed in the "ttl-security" filter and are only allowed
015 * if the TTL on incoming packets is 254, meaning they are exactly
016 * one hop away.
017 *
018 * Three parts to this script. First we set the TTL to 255. Then
019 * we make a filter that discards traffic where TTL != 254. Then
020 * we put that filter in lo0.
021 *
022 * We don't want to interfere with an existing filter on lo0, so
023 * we have to look at the current state. If there's no filter,
024 * we make one and put a "then accept" on it. If there's a single
025 * filter, we turn it into a filter list with our's at the front of
026 * the list. If there's already a filter list, we add our's to the
027 * front of the list.
028 */
029 match configuration {
030 var $all = protocols/bgp/group[apply-macro/name == 'ttl-security'];
031 var $tag = "transient-change";
032 var $lo0 = interfaces/interface[name == 'lo0']
033 /unit[name == '0']/family/inet/filter;
034 if ($all) {
035 var $content = <multihop> {
036 <ttl> 255;
037 }
038
039 for-each ($all) {
040 call jcs:emit-change($tag, $content);
041 }
042
043 var $last-term = {
044 if (not($lo0/input) && not($lo0/input-list)) {
045 <term> {
046 <name> "else";
047 <then> {
048 <accept>;
049 }
050 }
051 }
052 }
053
054 var $filter = {
055 if ($lo0/input) {
056 <input-list> "ttl-security";
057 <input-list> $lo0/input;
058 } else if ($lo0/input-list) {
059 var $name = $lo0/input-list[1];
060 <input-list insert="before" name=$name> "ttl-security";
061 } else {
062 <input> "ttl-security";
063 }
064 }
065
066 <transient-change> {
067 <firewall> {
068 <filter> {
069 <name> "ttl-security";
070 <term> {
071 <name> "gtsm";
072 <from> {
073 for-each ($all/neighbor/name) {
074 <source-address> .;
075 }
076 <protocol> "tcp";
077 <port> 179;
078 <ttl-except> 254;
079 }
080 <then> {
081 <discard>;
082 }
083 }
084 copy-of $last-term;
085 }
086 }
087 <interfaces> {
088 <interface> {
089 <name> "lo0";
090 <unit> {
091 <name> "0";
092 <family> {
093 <inet> {
094 <filter> {
095 copy-of $filter;
096 }
097 }
098 }
099 }
100 }
101 }
102 }
103 }
104 }
XML Script Contents
01 <?xml version="1.0"?>
02 <script version="0.1">
03 <title>ttl-security.slax</title>
04 <author>phil</author>
05 <synopsis>Easy mechanism to turn on TTL-based security (GTSM)</synopsis>
06 <keyword>GTSM</keyword>
07 <keyword>BGP</keyword>
08 <keyword>TTL</keyword>
09
10 <description>
11 We need to make an lo0 filter based on our BGP config. Any
12 members of BGP groups with "apply-macro ttl-security" turned
13 on are listed in the "ttl-security" filter and are only allowed
14 if the TTL on incoming packets is 254, meaning they are exactly
15 one hop away. This script is based on:
16 http://juniper.cluepon.net/index.php/ER_BGP_TTL_Security_support_enhancements
17 </description>
18 <implementation>
19 Three parts to this script. First we set the TTL to 255. Then
20 we make a filter that discards traffic where TTL != 254. Then
21 we put that filter in lo0.
22
23 We don't want to interfere with an existing filter on lo0, so
24 we have to look at the current state. If there's no filter,
25 we make one and put a "then accept" on it. If there's a single
26 filter, we turn it into a filter list with our's at the front of
27 the list. If there's already a filter list, we add our's to the
28 front of the list.
29 </implementation>
30
31 <example>
32 <config>ttl-security.conf</config>
33 <title>An example with no lo0</title>
34 <output>ttl-security.output</output>
35 </example>
36 <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml"
37 src="../../../../../web/leaf.js" type="text/javascript"/>
38 </script>