Automation
Showing results for 
Search instead for 
Do you mean 

Scripting How-To: Control firewall filter terms for certain time ranges

by Cordelia on ‎08-09-2015 08:49 AM - edited on ‎09-11-2017 05:16 PM by Administrator Administrator

Control Firewall Filter Terms for Certain Time Ranges

 

For SLAX version 1.0 and higher, you can activate or deactivate firewall filter terms based on configured time-ranges when you use a time-based event script in tandem with a commit script.

 

You can immediately create the configuration required for the event script without waiting for the event to occur. This automates activating firewall filter terms during specified time ranges. This is used to create a time-based stateless firewall filter.


The event script time-based-filters.slax and the commit script cs-time-based-filters.slax are paired to create time-based stateless firewall filters. The scripts employ user-defined arguments from the router configuration to automatically activate and deactivate specified filter terms at designated periods. You load the script files, enable them, and mark the filter terms with appropriate macros that provide instructions regarding the times when the firewall terms should be enabled or disabled.
 

System Requirements

 The minimum Junos OS Release is 9.3. Additionally, this script is only supported on the  following Junos OS releases:


  • 9.3R5
  • 9.4R4
  • 9.5R3
  • 9.6R2

Set Up

 

  1. Copy the script time-based-filters.slax to the /var/db/scripts/event directory on the router.
  2. Copy the script cs-time-based-filters.slax to the /var/db/scripts/commit directory on the router.

    NOTE: On dual-routing engine (dual-RE) systems you need to perform all of the initial steps on each of the routing engines—you must copy the scripts to their respective directories and enable both the event script and the commit script on each routing engine.

    1	[edit event-options event-script]
    2	user@host# set file time-based-filters.slax
    3	[edit system scripts commit]
    4	user@host# set file cs-time-based-filters.slax
  3. Add time-range configuration macros to any firewall filter term that should be enabled or disabled at specific times. These are added by entering the apply-macro statement under the firewall filter term hierarchy, with a macro name of either active-time-range or inactive-time-range.

    The basic outline of the time-range macro is:
1 term <rule-name> { 
2 apply-macro (active-time-range | inactive-time-range) {
3 start-time <start-time>;
4 stop-time <stop-time>;
5 }

     NOTE: Macros are a simple way to embed user-defined syntax, e.g. a name-value pair, inside Junos OS

     configuration.

 

4. To add a macro, enter the configuration mode on the routing device, navigate to the hierarchy of the

     firewall filter that should be time-based, and add the desired time-range macro with the time-range
     defined.

5. The default state for the firewall filter term will be the opposite of the time-range state designated in the

     macro. For example, if an active-time-range is specified for a firewall term, the term will be set to inactive

     by default unless the current time falls within the active-time-range that is specified. Within a time-range

     macro, both the start-time and stop-time statements must be configured to specify the start of the

     active/inactive period.

6.  Enable the scripts by adding the file statement and script filename to the appropriate hierarchy level for

     the script type. Only superusers can enable scripts in the configuration.

 

Time Formats

 

Time is specified in one of the formats listed below, where HH is in 24 hour format, and MM can only be 00, 15, 30, or 45.

  • HH:MM - The time applies to every day at the HH:MM specified.
  • weekdays HH:MM - The time applies to only weekdays at the HH:MM specified.
  • weekends HH:MM - The time applies to only weekends at the HH:MM specified.
  • mon HH:MM - The time applies on the day of the week (sun, mon, tue, etc) at the HH:MM specified.

Use the following examples of firewall filter terms with configured time-range macros to determine how to set up your own time-range macros. The term name is user-defined:


This filter term will only be active from 8:00 a.m. to 5:00 p.m.:

 

 

1	term day-term {
2	    apply-macro active-time-range {
3	        start-time 08:00;
4	        stop-time 17:00;
5	    }
6	    ...
7	}

This term will be inactive from 3:00 p.m. to 6:00 p.m.: 

 

 

 

1	term not-afternoon-term {
2	    apply-macro inactive-time-range {
3	        start-time 15:00;
4	        stop-time 18:00;
5	    }
6	    ...
7	}

This term will be active from Monday to Wednesday from 12:00 a.m. to 12:00 a.m. (24:00): 

 

 

 

1	term multiple-days {
2	    apply-macro active-time-range {
3	        start-time "mon 00:00";
4	        stop-time "wed 24:00";
5	    }
6	    ...
7	}

This term will be active from 5:00 p.m. to 8:00 p.m. on weekdays:

 

 

1	term night {
2	    apply-macro active-time-range {
3	        start-time "weekdays 17:00";
4	        stop-time "weekdays 20:00";
5	    }
6	    ...
7	}

 

 

How to Run

The time-based filter script will run automatically at the start and stop times specified and will activate or deactivate the firewall terms whose state should be changed based on the start and stop times specified in the time-range macros in the configuration.


Term activations or deactivations will result in a syslog message to the external facility with a severity of info, for example:

 

1	Jul 30 13:51:02 r2d2-re0 cscript: time-based-filters script activating term weekdays
2	Jul 30 13:51:02 r2d2-re0 cscript: time-based-filters script deactivating term default
 

Example Implementation

For example, assume you want to set a family inet filter with the filter name re-protect to be time-based. You could do this by following these steps:

  1. Enter configuration mode and navigate to firewall family inet filter re-protect:

    1	user@host> configure
    2	 Entering configuration mode
    3	[edit]
    4	user@host# edit firewall family inet filter re-protect
  2. Add the time-range macros to the filters. The example below creates a term rule called block-html that sets the active range of the filter from 8 a.m. to 5 p.m:

    1	[edit firewall family inet filter re-protect]
    2	user@host# set term block-html apply-macro active-time-range start-time 08:00
    3	[edit firewall family inet filter re-protect]
    4	user@host# set term block-html apply-macro active-time-range stop-time 17:00
  3. When finished setting up time-range macros, commit the configuration changes:

    1	[edit]
    2	user@host# commit and-quit
 

Notes and Restrictions

Below are restrictions to be aware of when using time-range macros and the time-based scripts in this section. These are in addition to the system requirements restrictions listed previously.

  • Only the Coordinated Universal Time (UTC) time-zone is supported. If a different time-zone is configured the commit will fail with an error.
  • You cannot include both active-time-range and inactive-time-range for the same term. Multiple ranges of the same type can be included by appending -# to the end to distinguish each range. (e.g. active-time-range-1, active-time-range-2, etc.)
  • These configuration elements are reserved for use by the time-based filter script:

    • groups time-based-filters-group
    • event-options generate-event time-based-filters-event
    • event-options policy time-based-filters-policy
  • A maximum of 10 unique HH:MM times can be configured, including [event-options generate-events]. If you try to configure more than 10, a commit error will result. 
  • Ensure that all filter terms are not deactivated at the same time; if they are, commit will fail.
  • Counters in a time-based term lose their value when the term is deactivated.
  • If your system time is ever manually changed, you must do one of the following to ensure that time events are on the correct time:

    • commit full
    • restart event-processing or 
    • request system scripts event-scripts reload
  • On a dual routing engine (dual-RE) system, time must be synchronized between the two REs. It is recommended that both REs be synchronized to an NTP server.

Source Code and GitHub Links

 

001	/*
002	 * Author        : Curtis Call
003	 * File          : cs-time-based-filters.slax
004	 * Version       : 1.1
005	 * Last Modified : August 7, 2009
006	 * Platform      : all
007	 * Release       : 9.3 and above
008	 * Minimum Revisions:
009	 * JUNOS 9.3:  (9.3R5 or 9.3S equivalent)
010	 * JUNOS 9.4:  (9.4R4)
011	 * JUNOS 9.5:  (9.5R3)
012	 * JUNOS 9.6:  (9.6R2)
013	 * JUNOS 10.0: (10.0R1)
014	 *
015	 * Description   : time-based-filters.slax and cs-time-based-filters.slax
016	 * time-based-filters.slax and cs-time-based-filters.slax are an event script
017	 * and commit script pair used when a time-based stateless firewall filter is
018	 * desired.  They function by deactivating the filter terms at designated
019	 * periods and activating them at the proper time. This is all performed
020	 * automatically by the scripts, the only action that the operator has to take
021	 * is to load the script files, enable them, and mark the filter terms with
022	 * the appropriate macros which provide instructions on when the terms should
023	 * be enabled and disabled.
024	 */
025	 
026	version 1.0;
027	 
028	ns junos = "http://xml.juniper.net/junos/*/junos";
029	ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
030	ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
031	 
032	import "../import/junos.xsl";
033	 
034	/* Import from the time-based-filters.slax script */
035	import "../event/time-based-filters.slax";
036	 
037	/*
038	 * This is needed here instead of in the junos.xsl import file because there is
039	 * a match / in the imported event file as well.
040	 */
041	match / {
042	    <commit-script-results> {
043	        apply-templates commit-script-input/configuration;
044	    }
045	}
046	 
047	/* Configuration items */
048	var $time-based-filters-event-prepend = "time-based-filters-event";
049	var $time-based-filters-policy = "time-based-filters-policy";
050	var $time-based-filters-group = "time-based-filters-group";
051	 
052	/* The version of the event and commit script MUST match. */
053	var $commit-script-version = "1.1";
054	 
055	match configuration {
056	 
057	    /*
058	    * First of all, make sure the event and commit script version match if they
059	    * do not then terminate immediately.
060	    */
061	    if( $commit-script-version != $event-script-version ) {
062	        <xsl:message terminate="yes"> "Your " _ $commit-script-name _ " version is different from your " _ $event-script-name _ " version.";
063	    }
064	     
065	    /*
066	     * Error if there is a non-UTC time-zone configured.  This is unsupported with
067	     * this script.
068	     */
069	    var $valid-time-zone = { call is-utc-time-zone(); }
070	    if( $valid-time-zone == $false ) {
071	        <xsl:message terminate="yes"> "JUNOS devices using the cs-time-based-filters script must use the UTC time-zone.";
072	    }
073	     
074	    /*
075	     * Check if this is a valid version or not (see note at top of script).  If
076	     * invalid version then log a xnm:warning and syslog indicating such and exit.
077	     */
078	     var $valid-version = { call is-valid-version(); }
079	     if( $valid-version == $true ) {
080	        call main();
081	     }
082	     else {
083	        <xnm:warning> {
084	            <message> "The cs-time-based-filters script is not supported in this JUNOS version.";
085	        }
086	        <syslog> {
087	            <message> "The cs-time-based-filters script is not supported in this JUNOS version.";
088	        }
089	     }
090	}
091	 
092	template main() {
093	    /* Record pointer to event-options */
094	    var $event-options = event-options;
095	     
096	    /* Record pointer to top */
097	    var $configuration = .;
098	 
099	    /* Pull in candidate configuration - for inactive elements */
100	    var $get-candidate-rpc =    <get-configuration database="candidate"> {
101	                                    <configuration> {
102	                                        <groups>;
103	                                        <event-options>;
104	                                        <firewall>;
105	                                        <logical-systems>;
106	                                    }
107	                                }
108	    var $candidate-configuration = jcs:invoke( $get-candidate-rpc );
109	     
110	    /* Look for macros in firewall stanza */
111	    var $firewall-macros = $candidate-configuration/firewall/filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
112	    var $firewall-family-macros = $candidate-configuration/firewall/family//filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
113	    var $groups-firewall-macros = $candidate-configuration/groups/firewall/filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
114	    var $groups-firewall-family-macros = $candidate-configuration/groups/firewall/family//filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
115	    var $logical-systems-firewall-macros = $candidate-configuration/logical-systems/firewall/filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
116	    var $logical-systems-firewall-family-macros = $candidate-configuration/logical-systems/firewall/family//filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
117	    var $groups-logical-systems-firewall-macros = $candidate-configuration/groups/logical-systems/firewall/filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
118	    var $groups-logical-systems-firewall-family-macros = $candidate-configuration/groups/logical-systems/firewall/family//filter/term[starts-with(apply-macro/name, $active-range-macro) or starts-with(apply-macro/name, $inactive-range-macro)];
119	 
120	    /* Combine them all into a single node set */
121	    var $firewall-terms = $firewall-macros | $firewall-family-macros | $groups-firewall-macros | $groups-firewall-family-macros |
122	                          $logical-systems-firewall-macros | $logical-systems-firewall-family-macros | $groups-logical-systems-firewall-macros |
123	                          $groups-logical-systems-firewall-family-macros;
124	     
125	    /* Go through each macro - look for errors - generate time-based events if needed */
126	    for-each( $firewall-terms ) {
127	         
128	        var $term-name = name;
129	        /* time range macros */
130	        var $time-range-macros = ./apply-macro[starts-with(name, $active-range-macro) or starts-with(name, $inactive-range-macro)];
131	             
132	        /* Verify the group of time range macros first, they need to either start with active or inactive... */
133	         
134	        var $default-status = {
135	            if( starts-with( $time-range-macros[1]/name , $active ) ) {
136	                expr $inactive;
137	            }
138	            else {
139	                expr $active;
140	            }
141	        }
142	         
143	        var $valid-range-group = {
144	            if( $default-status == $active and $time-range-macros/name[starts-with(., $active)] ) {
145	                expr $false;
146	            }
147	            else if( $default-status == $inactive and $time-range-macros/name[starts-with(., $inactive)] ) {
148	                expr $false;
149	            }
150	            else {
151	                expr $true;
152	            }
153	        }
154	         
155	        if( $valid-range-group == $false ) {
156	            <xnm:error> {
157	                call jcs:edit-path();
158	                <message> $term-name _ " cannot have both active and inactive time ranges.";
159	            }
160	        }
161	 
162	        /* Go through all time ranges, look for errors */
163	        for-each( $time-range-macros ) {
164	 
165	            var $range-status = {
166	                /* The opposite of the default status */
167	                if( $default-status == $active ) {
168	                    expr $inactive;
169	                }
170	                else {
171	                    expr $active;
172	                }
173	            }
174	             
175	            /* Does it have a valid start time? */
176	            var $start-time-range = data[name == $start-time-field]/value;
177	            var $start-time-raw = { call get-time-from-range( $range = $start-time-range ); }
178	            var $start-time = { call adjust-time( $time = $start-time-raw ); }
179	            var $valid-start-time = { call is-valid-time-range( $range = $start-time-range ); }
180	            if( $valid-start-time == $false ) {
181	                <xnm:error> {
182	                    call jcs:edit-path();
183	                    call jcs:statement( $dot = data[name == $start-time-field]/value );
184	                    <message> $term-name _ " does not have a valid " _ $start-time-field _ " defined in their " _ ./name _ " macro.";
185	                }
186	            }
187	             
188	            
189	            /* Does it have a valid stop time? */
190	            var $stop-time-range = data[name == $stop-time-field]/value;
191	            var $stop-time-raw = { call get-time-from-range( $range = $stop-time-range ); }
192	            var $stop-time = { call adjust-time( $time = $stop-time-raw ); }
193	            var $valid-stop-time = { call is-valid-time-range( $range = $stop-time-range ); }
194	            if( $valid-stop-time == $false ) {
195	                <xnm:error> {
196	                    call jcs:edit-path();
197	                    call jcs:statement( $dot = data[name == $stop-time-field ]/value );
198	                    <message> $term-name _ " does not have a valid " _ $stop-time-field _ " defined in their " _ ./name _ " macro.";
199	                }
200	            }
201	             
202	            /* Is the start-time and stop-time pair valid? */
203	            var $valid-range-pair = { call is-valid-range-pair( $start-range = $start-time-range, $stop-range = $stop-time-range ); }
204	            if( $valid-range-pair == $false ) {
205	                <xnm:error> {
206	                    call jcs:edit-path();
207	                    <message> $term-name _ " does not have a valid time range pair: " _ $start-time-range _ " " _ $stop-time-range;
208	                }
209	            }
210	             
211	            /*
212	            * Now check if there is already a time-based event defined for the start-time and stop-time
213	            * and if they are already setup for the event script.
214	            *
215	            */
216	 
217	            /* Create a node-set so we can loop through the next section */
218	            var $time-events := {
219	                if( $valid-range-pair == $true and $valid-start-time == $true ) {
220	                    <time> $start-time;
221	                }
222	                if( $valid-range-pair == $true and $valid-stop-time == $true ) {
223	                    /* Translate a 24:00 to a 00:00 */
224	                    if( $stop-time == "24:00" ) {
225	                        <time> "00:00";
226	                    }
227	                    else {
228	                        <time> $stop-time;
229	                    }
230	                }
231	            }
232	          
233	            /* Create time events if needed */
234	            for-each( $time-events/time ) {
235	                var $time-event-name = $time-based-filters-event-prepend _ "-" _ .;
236	                var $time-event-value = . _ ":00";
237	                /* Does the time event already exist?  Then check it's time */
238	                if( $event-options/generate-event[name==$time-event-name] ) {
239	                    /* Check it's value, if it isn't the right time then send an error */
240	                    if( not( starts-with( $event-options/generate-event[name==$time-event-name]/time-of-day, $time-event-value ) ) ) {
241	                        <xnm:error> {
242	                            call jcs:edit-path($dot = $event-options/generate-event[name==$time-event-name]);
243	                            call jcs:statement($dot = $event-options/generate-event[name==$time-event-name]/time-of-day);
244	                            <message> "Needed time event is already defined but with the wrong time.";
245	                        }
246	                    }
247	                }
248	                else { /* It doesn't exist... create it... */
249	                    <change> {
250	                        <groups> {
251	                            <name> $time-based-filters-group;
252	                            <event-options> {
253	                                <generate-event> {
254	                                    <name> $time-event-name;
255	                                    <time-of-day> $time-event-value;
256	                                }
257	                            }
258	                        }
259	                    }
260	                }
261	             
262	                /* Verify that apply flags omit is present in the group, if not then add it */
263	                if( jcs:empty( $candidate-configuration/groups[name==$time-based-filters-group]/undocumented/apply-flags/omit ) ) {
264	                    <change> {
265	                        <groups> {
266	                            <name> $time-based-filters-group;
267	                            <undocumented> {
268	                                <apply-flags> {
269	                                    <omit>;
270	                                }
271	                            }
272	                        }
273	                    }
274	                }
275	             
276	                /* Verify that the apply group is present in event-options */
277	                if( jcs:empty( $candidate-configuration/event-options[apply-groups == $time-based-filters-group] ) ) {
278	                    <change> {
279	                        <event-options> {
280	                            <apply-groups> $time-based-filters-group;
281	                        }
282	                    }
283	                }
284	             
285	                /* Is the event policy already defined? If not then create it, this could happen multiple times when first created */
286	                if( jcs:empty( $event-options/policy[name == $time-based-filters-policy]/then/event-script[name == $event-script-name ] ) ) {
287	                    <change> {
288	                        <groups> {
289	                            <name> $time-based-filters-group;
290	                            <event-options> {
291	                                <policy> {
292	                                    <name> $time-based-filters-policy;
293	                                    <then> {
294	                                        <event-script> {
295	                                            <name> $event-script-name;
296	                                        }
297	                                    }
298	                                }
299	                            }
300	                        }
301	                    }
302	                }
303	             
304	                /* Is the event script line present?  If not then create it */
305	                if( jcs:empty( $event-options/event-script/file[name == $event-script-name] ) ) {
306	                    <change> {
307	                        <groups> {
308	                            <name> $time-based-filters-group;
309	                            <event-options> {
310	                                <event-script> {
311	                                    <file> {
312	                                        <name> $event-script-name;
313	                                    }
314	                                }
315	                            }
316	                        }
317	                    }
318	                }
319	 
320	                /* Is the event already defined as an event in the time-based-filters event policy? */
321	                if( jcs:empty( $event-options/policy[name == $time-based-filters-policy][events == $time-event-name ] ) ) {
322	                    /* If not already defined then define it */
323	                    <change> {
324	                        <groups> {
325	                            <name> $time-based-filters-group;
326	                            <event-options> {
327	                                <policy> {
328	                                    <name> $time-based-filters-policy;
329	                                    <events> $time-event-name;
330	                                }
331	                            }
332	                        }
333	                    }
334	                }
335	            }
336	        }
337	    }
338	     
339	    /* Go through each time-based-access event and delete it if no longer needed */
340	    for-each( $event-options/generate-event[starts-with( name, $time-based-filters-event-prepend ) ] ) {
341	        var $term-matches-event = { call term-matches-event( $firewall-terms, $event-time = time-of-day ); }
342	         
343	        /* If it matches no shift starts nor shift stops then delete it */
344	        if( $term-matches-event == $false ) {
345	            <change> {
346	                <groups> {
347	                    <name> $time-based-filters-group;
348	                    <event-options> {
349	                        <generate-event delete="delete"> {
350	                            <name> name;
351	                        }
352	                    }
353	                }
354	            }
355	        }
356	    }
357	 
358	    /* Go through each event in the event policy and delete it if no longer needed */
359	    var $full-prepend = $time-based-filters-event-prepend _ "-";
360	    for-each( $event-options/policy[name==$time-based-filters-policy]/events ) {
361	        var $event-time = substring-after( .,  $full-prepend);
362	        var $term-matches-event = { call term-matches-event( $firewall-terms, $event-time ); }
363	 
364	        /* Delete it if not present */
365	        if( $term-matches-event == $false  ) {
366	            <change> {
367	                <groups> {
368	                    <name> $time-based-filters-group;
369	                    <event-options> {
370	                        <policy> {
371	                            <name> $time-based-filters-policy;
372	                            <events delete="delete"> .;
373	                        }
374	                    }
375	                }
376	            }
377	        }
378	    }
379	     
380	    /* Delete the entire group if it isn't needed any longer - if no firewall terms then it isn't needed */
381	    if( jcs:empty( $firewall-terms ) ) {
382	        if( not( jcs:empty( event-options/policy[name==$time-based-filters-policy] ) ) ) {
383	            <change> {
384	                <groups delete="delete"> {
385	                    <name> $time-based-filters-group;
386	                }
387	            }
388	            <change> {
389	                <event-options> {
390	                    <apply-groups delete="delete"> $time-based-filters-group;
391	                }
392	            }
393	        }
394	    }
395	     
396	    /* Now run the event script template and make any changes to the filter terms that are needed */
397	    call generate-config-changes( $firewall-terms );
398	     
399	}
400	 
401	/* Searches through firewall terms looking for a match to the time in the event time-of-day, returns $true or $false */
402	template term-matches-event( $firewall-terms, $event-time ) {
403	    /* Adjust in case it starts with a 0 like 08:00, so we can try 8:00 also */
404	    var $adjusted-time = {
405	        if( starts-with( $event-time, "0" ) ) {
406	            expr substring-after( $event-time, "0" );
407	        }
408	        else {
409	            expr $event-time;
410	        }
411	    }
412	    var $response = {
413	        for-each( $firewall-terms/apply-macro[starts-with(name, $active-range-macro) or starts-with(name, $inactive-range-macro)]/data[name == $start-time-field or name == $stop-time-field ] ) {
414	            var $macro-time = { call get-time-from-range( $range = value ); }
415	             
416	            /* Adjust the firewall times to convert the 24:00 to a 00:00 */
417	            var $adjusted-macro-time = {
418	                if( $macro-time == "24:00" ) {
419	                    expr "00:00";
420	                }
421	                else {
422	                    expr $macro-time;
423	                }
424	            }
425	             
426	            if( starts-with( $event-time, $adjusted-macro-time ) or starts-with( $adjusted-time, $adjusted-macro-time ) ) {
427	                expr $true;
428	            }
429	        }
430	    }
431	    /* Return $true or $false based on the result of the $response */
432	    if( contains( $response, $true ) ) {
433	        expr $true;
434	    }
435	    else {
436	        expr $false;
437	    }
438	}

XML Script Contents 

 

001	<?xml version="1.0"?>
002	<script>
003	  <title>cs-time-based-filters.slax</title>
004	  <author>curtisstephencall</author>
005	  <synopsis>
006	    Activates/Deactivates firewall filter terms based on configured time-ranges.
007	  </synopsis>
008	  <coe>commit</coe>
009	  <type>filters</type>
010	 
011	  <description>
012	    <![CDATA[time-based-filters.slax and cs-time-based-filters.slax are an event script
013	    and commit script pair used when a time-based stateless firewall filter is
014	    desired.  They function by deactivating the filter terms at designated
015	    periods and activating them at the proper time. This is all performed
016	    automatically by the scripts, the only action that the operator has to take
017	    is to load the script files, enable them, and mark the filter terms with
018	    the appropriate macros which provide instructions on when the terms should
019	    be enabled and disabled.
020	 
021	    * Minimum JUNOS version is 9.3.  In addition, due to PR 452398 this script can
022	    * only be used with the following JUNOS versions as of the dailies mentioned:
023	    * JUNOS 9.3:  20090730 (9.3R5)
024	    * JUNOS 9.4:  20090730 (9.4R4)
025	    * JUNOS 9.5:  20090729 (9.5R3)
026	    * JUNOS 9.6:  20090701 (9.6R2)
027	    * JUNOS 10.0: 20090623 (10.0B1)
028	   
029	    (Must be used in combination with time-based-filters.slax).
030	 
031	     
032	    Installation
033	    ------------
034	    1. Copy the time-based-filters.slax script to the /var/db/scripts/event
035	    directory on all REs.
036	 
037	    2. Copy the cs-time-based-filters.slax script to the /var/db/scripts/commit
038	    directory on all REs.
039	 
040	    3. Configure: set system scripts commit file cs-time-based-filters.slax
041	 
042	    This is all that is required to setup the time-based-filters scripts.  No
043	    event policy configuration is necessary, the commit script will
044	    automatically generate all needed configuration.
045	 
046	 
047	    Time-Based Stateless Firewall Filters
048	    -------------------------------------
049	    To mark a filter as a time-based filter it is necessary to add either
050	    the "active-time-range" or "inactive-time-range" macro under the filter
051	    term and specify a start-time and stop-time for the term.
052	 
053	    start-time - The beginning time for the time-range
054	 
055	    stop-time - The ending time for the time-range
056	 
057	    Valid formats for start-time and stop-time are the following:
058	 
059	    HH:MM - The time occurs every day at the specified HH:MM (in 24 hour format).
060	 
061	    "weekdays HH:MM" - The time occurs Mon-Fri at the specified time
062	 
063	    "weekends HH:MM" - The time occurs Sat-Sun at the specified time
064	 
065	    "day HH:MM" where day = sat, sun, mon, etc - The time occurs on the given day
066	    at the specified time.
067	 
068	    MM must be 00, 15, 30, or 45.  HH should be from 00 to 24.  If HH is 24 then
069	    MM must be 00.
070	 
071	    Reversed time-ranges, where the stop-time occurs before the start-time (because
072	    the start-time begins at night and the stop-time occurs in the morning) are not
073	    allowed when using "weekdays" or "weekends".
074	 
075	    The default status of the term is the opposite of the selected time-range.  If
076	    active-time-range is used, then the default status outside of the given time-range
077	    is inactive.  The reverse is true for an inactive-time-range.
078	 
079	    Multiple time-ranges can be specified by appending a -# to each macro (the name
080	    must be unique).  They must all be of the same type within a term, either inactive
081	    or active.
082	 
083	 
084	    Reserved Configuration
085	    ----------------------
086	    The scripts reserve the following configuration elements and they will add
087	    and delete them as needed:
088	    groups time-based-filters-group
089	    generate-event time-based-filters-event*
090	    policy time-based-filters-policy
091	 
092	 
093	    Restrictions & Misc
094	    -------------------
095	    Only the UTC time-zone is supported due to PR 459078.  Using a different time-zone
096	    will result in a commit error.
097	 
098	    A maximum of 10 unique times can be supported per JUNOS device.  Going beyond this
099	    will result in a commit error.
100	 
101	    Be careful that all filter terms are not deactivated at the same time, if that
102	    occurs then the commit will fail.
103	 
104	    Counters in a time-based term will lose their value when the term is deactivated.
105	 
106	    The commit script will enforce the correct term status as part of the commit
107	    process as well.  This means that it is not necessary to wait until the start/stop
108	    of a term's time-range to have the term's status set correct.
109	 
110	    If you ever manually change your system time, then you need to do a "commit
111	    full" or "restart event-process" or "request system scripts event-scripts reload"
112	    because your time-of-day events will be off time.
113	 
114	    This should work for filters of any address family defined under firewall or groups
115	    as well as logical-systems.
116	 
117	    Term activations or deactivations will result in a syslog message to the external
118	    facility with severity info:
119	    Jul 30 13:51:02  r2d2-re0 cscript: time-based-filters script activating term weekdays
120	    Jul 30 13:51:02  r2d2-re0 cscript: time-based-filters script deactivating term default
121	 
122	 
123	    Dual-RE Systems
124	    ---------------
125	    On dual-re systems you need to copy the scripts into their respective directories
126	    and enable the commit script (set system scripts commit file ...) on both REs.
127	 
128	    Time must be synchronized between the two REs.  It is recommended that both REs
129	    are synchronized to a NTP server.
130	 
131	    The script will run on both REs but it will pause for a minute on the backup RE
132	    to allow the master RE to make the configuration change.  If there is a
133	    communication problem then the backup RE will make the needed configuration change
134	    but it will not synchronize its commit (unless the configuration forces it to).
135	 
136	 
137	    Problems
138	    --------
139	    The event script will attempt an exclusive commit at the start and stop
140	    times configured.  If other users are editing the configuration then
141	    the exclusive commit will fail and this will be logged into the syslog:
142	 
143	    Jan  4 04:00:01  EX2 cscript: %DAEMON-3: time-based-filters.slax unable to lock configuration database.
144	    Jan  4 04:00:01  EX2 cscript: %DAEMON-3: time-based-filters.slax configuration change failure on attempt #1 - retry in 5 minutes.
145	 
146	    This is sent to the daemon facility at severity error.  The script waits
147	    five more minutes before trying again.  This will continue every five
148	    minutes until the commit succeeds or until the maximum attempts of six has
149	    been reached at which point the script will terminate and log this:
150	 
151	    Jan  4 04:25:06  EX2 cscript: %DAEMON-3: time-based-filters.slax unable to lock configuration database.
152	    Jan  4 04:25:06  EX2 cscript: %DAEMON-3: time-based-filters.slax configuration changes could not be made after 6 attempts. - Script is exiting.
153	 
154	 
155	    The commit script and event script work together so it is essential that
156	    they are using the same version.  If the commit script detects that there
157	    is a different event script version in use then it will fail the commit and
158	    report:
159	 
160	    error: Your cs-time-based-filters.slax version is different from your time-based-filters.slax version.
161	    error: 2 errors reported by commit scripts
162	    error: commit script failure]]>
163	  </description>
164	  <example>
165	    <title>Example time-range macros</title>
166	    <description>
167	     <![CDATA[This filter term should only be active from 8:00am to 5:00pm
168	     term day-term {
169	         apply-macro active-time-range {
170	             start-time 08:00;
171	             stop-time 17:00;
172	         }
173	         ...
174	     }
175	 
176	     This term should be inactive from 3:00pm to 6:00pm
177	     term not-afternoon-term {
178	         apply-macro inactive-time-range {
179	             start-time 15:00;
180	             stop-time 18:00;
181	         }
182	         ...
183	     }
184	 
185	     This term should be active from monday to wednesday from 12:00am to 12:00am
186	     term multiple-days {
187	         apply-macro active-time-range {
188	             start-time "mon 00:00";
189	             stop-time "wed 24:00";
190	         }
191	         ...
192	     }
193	 
194	     This term should be active from 5:00pm to 8:00pm on weekdays
195	     term night {
196	         apply-macro active-time-range {
197	             start-time "weekdays 17:00";
198	             stop-time "weekdays 20:00";
199	         }
200	         ...
201	     }
202	 
203	     This term should be active from 10am-12pm and 2pm-4pm
204	     term multi-range {
205	         apply-macro active-time-range-1 {
206	             start-time 10:00;
207	             stop-time 12:00;
208	         }
209	         apply-macro active-time-range-2 {
210	             start-time 14:00;
211	             stop-time 16:00;
212	         }
213	         ...
214	     }]]>
215	    </description>
216	  </example>
217	  <keyword>commit</keyword>
218	  <keyword>slax</keyword>
219	  <keyword>firewall</keyword>
220	  <keyword>filters</keyword>
221	  <keyword>time</keyword>
222	  <keyword>time-based</keyword>
223	 
224	  <xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml"
225	                src="../../../../../web/leaf.js"
226	            type="text/javascript"/>
227	</script>