Blog of Christiaan Rademan.
VI / VIM is a powerful editor and I built this small reference of commands that can be used.
VIM Typically functions in different modes.
Command mode
Possibly the most important thing to know is that when you're in command mode you can't insert text immediately. You first need to issue an insert, append, or open command to insert text.
Visual mode
Visual mode is used for copying and pasting for example.
Insert mode
Insert mode is used to add and append to the file.
Last line mode
You can only get to last line mode from command mode, and you get into last line mode by pressing the colon key.
:help keyword - open help for keyword
:close - close current pane
:wq or :x or ZZ - write (save) and quit
:q - quit (fails if there are unsaved changes)
:q! or ZQ - quit and throw away unsaved changes
:e filename - edit another file
:o file - open file
:saveas file - save file as
:w - write (save) the file, but don't exit
:Explore - Directory listing
h - move cursor left
j - move cursor down
k - move cursor up
l - move cursor right
H - move to top of screen
M - move to middle of screen
L - move to bottom of screen
w - jump forwards to the start of a word
W - jump forwards to the start of a word (words can contain punctuation)
e - jump forwards to the end of a word
E - jump forwards to the end of a word (words can contain punctuation)
b - jump backwards to the start of a word
B - jump backwards to the start of a word (words can contain punctuation)
0 - jump to the start of the line
^ - jump to the first non
$ - jump to the end of the line
g_ - jump to the last non
gg - go to the first line of the document
G - go to the last line of the document
5G - go to line 5
fx - jump to next occurrence of character x
tx - jump to before next occurrence of character x
} - jump to next paragraph (or function/block, when editing code)
{ - jump to previous paragraph (or function/block, when editing code)
zz - center cursor on screen
Ctrl + b - move back one full screen
Ctrl + f - move forward one full screen
Ctrl + d - move forward 1/2 a screen
Ctrl + u - move back 1/2 a screen
Tip Prefix a cursor movement command with a number to repeat it. For example, 4j moves down 4 lines.
i - insert before the cursor
I - insert at the beginning of the line
a - insert (append) after the cursor
A - insert (append) at the end of the line
o - append (open) a new line below the current line
O - append (open) a new line above the current line
ea - insert (append) at the end of the word
Esc - exit insert mode
r - replace a single character
J - join line below to the current one
cc - change (replace) entire line
cw - change (replace) to the end of the word
c$ - change (replace) to the end of the line
s - delete character and substitute text
S - delete line and substitute text (same as cc)
xp - transpose two letters (delete and paste)
u - undo
Ctrl + r - redo
v - start visual mode, mark lines, then do a command (like y
V - start linewise visual mode
o - move to other end of marked area
Ctrl + v - start visual block mode
O - move to other corner of block
aw - mark a word
ab - a block with ()
aB - a block with {}
ib - inner block with ()
iB - inner block with {}
Esc - exit visual mode
> - shift text right
< - shift text left
y - yank (copy) marked text
d - delete marked text
~ - switch case
yy - yank (copy) a line
2yy - yank (copy) 2 lines
yw - yank (copy) the characters of the word from the cursor position to the start of the next word
y$ - yank (copy) to end of line
p - put (paste) the clipboard after cursor
P - put (paste) before cursor
dd - delete (cut) a line
2dd - delete (cut) 2 lines
dw - delete (cut) the characters of the word from the cursor position to the start of the next word
D - delete (cut) to the end of the line
d$ - delete (cut) to the end of the line
x - delete (cut) character
/pattern - search for pattern
?pattern - search backward for pattern
vpattern - 'very magic' pattern: non
n - repeat search in same direction
N - repeat search in opposite direction
:%s/old/new/g - replace all old with new throughout file
:%s/old/new/gc - replace all old with new throughout file with confirmations
:noh - remove highlighting of search matches
:split filename - split window and load another file
ctrl-w up arrow - move to window above
ctrl-w left arrow - move to window left
ctrl-w up right arrow - move to window right
ctrl-w up down arrow - move to window below
ctrl-w ctrl-w - move cursor to another window (cycle)
ctrl-w_ - maximize current window
ctrl-w= - make all equal size
10 ctrl-w+ - increase window size by 10 lines
:vsplit file - vertical split
:sview file - same as split, but readonly
:hide - close current window
:only - keep only this window open
:ls - show current buffers
:b 2 - open buffer #2 in this window
VI Improved (VIM) is my editor of choice. I prefer to use this as development and scripting IDE. This is also seems to be the general view of the open-source community. VIM is ubiquitous, fast, and never crashes. And it can do just about anything!
You require vim compiled with Python support.
apt-get install vim-nox-py2
$ brew update $ brew install vim
$ sudo port update $ sudo port install vim +huge +python27
VIM has several extension managers, but the one I strongly recommend is Vundle. Think of it as pip for VIM. It makes installing and updating packages trivial.
$ git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim
This command downloads the Vundle plugin manager and chucks it in your VIM bundles directory. Now you can manage all your extensions from the .vimrc configuration file.
Add the file to your user’s home directory:
$ touch ~/.vimrc
Now set up Vundle in your .vimrc and some extra plugins using:
set nocompatible " be iMproved, required filetype off " required " set the runtime path to include Vundle and initialize set rtp+=~/.vim/bundle/Vundle.vim call vundle#begin() " let Vundle manage Vundle, required Plugin 'gmarik/Vundle.vim' " Add all your plugins here (note older versions of Vundle used Bundle instead of Plugin) Plugin 'tmhedberg/SimpylFold' Plugin 'vim-scripts/indentpython.vim' Bundle 'Valloric/YouCompleteMe' Plugin 'scrooloose/syntastic' Plugin 'nvie/vim-flake8' Plugin 'jnurmine/Zenburn' Plugin 'altercation/vim-colors-solarized' Plugin 'Lokaltog/powerline', {'rtp': 'powerline/bindings/vim/'} " All of your Plugins must be added before the following line call vundle#end() " required filetype plugin indent on " required " Enable folding set foldmethod=indent set foldlevel=99 " Enable folding with the spacebar nnoremap <space> za " YCM map <leader>g :YcmCompleter GoToDefinitionElseDeclaration<CR> let g:ycm_autoclose_preview_window_after_insertion=1 let g:ycm_add_preview_to_completeopt=1 set encoding=utf-8 syntax on set tabstop=4 set softtabstop=4 set shiftwidth=4 set expandtab set autoindent set fileformat=unix autocmd FileType python set textwidth=79 autocmd FileType sh nnoremap <F5> :!%:p<CR> autocmd FileType php nnoremap <F5> :!clear & php %:p<CR> autocmd FileType python nnoremap <F5> :!clear & python %:p<CR> autocmd FileType python nnoremap <F5> :!clear & python %:p<CR> autocmd FileType python nnoremap <F6> :!clear & pudb %:p<CR> autocmd FileType python map <buffer> <F4> :call Flake8()<CR> autocmd FileType python imap <F3> <Esc>:YcmCompleter GetDoc<CR>i set nu set cursorline highlight LineNr ctermbg=white ctermfg=black highlight CursorLineNr ctermbg=darkred ctermfg=black highlight ExtraWhitespace ctermbg=red guibg=red match ExtraWhitespace /\s\+$/ autocmd BufWinEnter * match ExtraWhitespace /\s\+$/ autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/ autocmd InsertLeave * match ExtraWhitespace /\s\+$/ autocmd BufWinLeave * call clearmatches() set laststatus=2 hi statusline ctermbg=black ctermfg=grey let python_highlight_all = 1 if has('gui_running') set background=dark colorscheme solarized else colorscheme zenburn endif "python with virtualenv support py << EOF import os import sys if 'VIRTUAL_ENV' in os.environ: project_base_dir = os.environ['VIRTUAL_ENV'] activate_this = os.path.join(project_base_dir, 'bin/activate_this.py') execfile(activate_this, dict(__file__=activate_this)) EOF
Fire up VIM and run to install all the plugins:
:PluginInstall
This command tells Vundle to work its magic – downloading all the plugins and installing/updating them for you.
Install YCM - Important for autocomplete
$ cd ~/.vim/bundle/YouCompleteMe
$ ./install.sh
That’s it. You’re now set up!!
Short introductions to above plugins installed...
Plugin 'tmhedberg/SimpylFold'
Most “modern” IDEs provide a way to collapse (or fold) methods and classes, showing you just the class/method definition lines instead of all the code. Use <space bar> or za to hide or unhide class cursor is on.
Plugin 'vim-scripts/indentpython.vim'
Autoindent will help but in some cases (like when a function signature spans multiple lines), it doesn’t always do what you want, especially when it comes to conforming to PEP8 standards. To fix that, we can use the indentpython.vim extension
Bundle 'Valloric/YouCompleteMe'
Under the hood YouCompleteMe uses a few different auto-completers (including Jedi for Python), and it needs some C libraries to be installed for it to work correctly. The docs have very good installation instructions so I won’t repeat them here, but be sure you follow them.
Plugin 'scrooloose/syntastic'
Plugin 'nvie/vim-flake8'
You can have VIM check your syntax on each save with the syntastic extension including PEP8 checking.
Plugin 'jnurmine/Zenburn'
Plugin 'altercation/vim-colors-solarized'
Color schemes work in conjunction with the basic color scheme that you are using. Check out solarized for GUI mode, and Zenburn for terminal mode
Plugin 'Lokaltog/powerline', {'rtp': 'powerline/bindings/vim/'}
Powerline is a status bar that displays things like the current virtualenv, git branch, files being edited, and much more.
It’s written in Python, and it supports a number of other environments like zsh, bash, tmux, and IPython.
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Based on this article I am using GITHUB http://www.github.com for hosting my repositories securely online. Code is hosted on GITHUB makes the code easy to browse, download, fork, etc.
Cloning a project is creating a local copy on your host of a remote repository.
$ git clone https://github.com/vision1983/nfw.git
On GITHUB you can create a fork which is a copy of repository hosted on GITHUB within your own GITHUB space.
Once you pushed your changes to own copy on GITHUB you can do a pull request on GITHUB which will inform the maintainers of the original project that you wish to merge your changes upstream.
Create a repository on GITHUB without initializing.
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git remote add origin https://github.com/vision1983/test.git
$ git push -u origin master
git remote add origin https://github.com/vision1983/test.git git push -u origin master
To commit changes you need to stage the changes using the following commands:
Add file to repository
$ git add file
Remove file from repository
$ git del file
Before committing you can undo or checkout original file
$ git checkout file
Commit changes locally
$ git commit -a
Finally upload or push to GITHUB
$ git push
Sync a fork of a repository to keep it up-to-date with the upstream repository.
Before you can sync your fork with an upstream repository, you must configure a remote that points to the upstream repository in GITHUB.
List current configured remote repository for your fork
$ git remote -v origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch) origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
Specify a new remote upstream repository that will be synced with the fork
$ git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.
Verify the new upstream repository you've specified for your fork
$ git remote -v origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch) origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push) upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch) upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)
Fetch the branches and their respective commits from the upstream repository. Commits to master will be stored in a local branch, upstream/master
$ git fetch upstream remote: Counting objects: 75, done. remote: Compressing objects: 100% (53/53), done. remote: Total 62 (delta 27), reused 44 (delta 9) Unpacking objects: 100% (62/62), done. From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY * [new branch] master -> upstream/master
Check out your fork's local master branch
$ git checkout master
Switched to branch 'master'
Merge the changes from upstream/master into your local master branch. This brings your fork's master branch into sync with the upstream repository, without losing your local changes
$ git merge upstream/master
Git has the ability to tag specific points in history as being important. Typically people use this functionality to mark release points (1.0.0, and so on)
List your tags
$ git tag 0.0.1 0.0.2
Git uses two main types of tags
Annotated as per GIT Documentation
Annotated tags, however, are stored as full objects in the Git database. They’re checksummed; contain the tagger name, email, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG). It’s generally recommended that you create annotated tags so you can have all this information; but if you want a temporary tag or for some reason don’t want to keep the other information, lightweight tags are available too.
Creating an annotated tag
The easiest way is to specify -a when you run the tag command.
$ git tag -a 0.0.2 -m "my version 0.0.2" $ git tag 0.0.0 0.0.1 0.0.2
The -m specifies a tagging message, which is stored with the tag.
You can see the tag data along with the commit that was tagged by using the git show command
$ git show 0.0.2
Lightweight as per GIT Documentation
A lightweight tag is very much like a branch that doesn’t change. It just points to a specific commit.
To create a lightweight tag, don’t supply the -a, -s, or -m option
$ git tag 0.0.3 $ git tag 0.0.0 0.0.1 0.0.2 0.0.3
When you run git show on the tag, you don’t see the extra tag information as per with annotated tag.
You can also tag commits after you’ve moved past them.
Retrieve commit history looks like this
$ git log --pretty=oneline
Tag based on checksum from history
$ git tag -a 0.0.6 [checksum]
By default, the git push command doesn’t transfer tags to remote servers. You will have to explicitly push tags to a shared server after you have created them.
$ git push origin [tagname]
If you have a lot of tags that you want to push up at once, you can
$ git push origin --tags
Delete tag locally
$ git tag -d 0.0.1
Delete tag from upstream
$ git push origin :refs/tags/1.0.5
Now, when someone else clones or pulls from your repository, they will get all your tags as well.
In your GITHUB project, you need to keep your master branch clean, by clean I mean without any changes, like that you can create at any time a branch from your master. Each time, that you want to commit a bug or a feature, you need to create a branch for it, which will be a copy of your master branch.
When you do a pull request on a branch, you can continue to work on another branch and make another pull request on this other branch.
Before creating a new branch, pull the changes from upstream. Your master needs to be up to date.
Create the branch on your local machine and switch in this branch
$ git checkout -b [name_of_your_new_branch]
Push the branch on github
$ git push origin [name_of_your_new_branch]
When you want to commit something in your branch, be sure to be in your branch.
You can see all branches created by using
$ git branch
See details on branches for origin/GITHUB
$ git remote show origin
Switch to a branch
$ git checkout [name_of_your_new_branch]
Pull updates from branch on GITHUB
$ git pull origin [name_of_your_new_branch]
Push updates to your branch on GITHUB
$ git push origin [name_of_your_new_branch]
Delete a branch on your local filesystem
$ git branch -d [name_of_your_new_branch]
Force the deletion of local branch on your filesystem
$ git branch -D [name_of_your_new_branch]
Delete the branch on github
$ git push origin :[name_of_your_new_branch]
I've recently started working on new open-source projects and decided to publish a post a basic tutorial on how to package your Python code.
This tutorial doesn't describe the only way of doing things, merely one specific approach that I use.
Python module/package names should generally follow the following constraints:
The structure below
Example:
myproject/ myproject/ __init__.py a_module.py setup.py setup.cfg docs/ tests/ Authors README.rst LICENSE ChangeLog MANIFEST.in requirements.txt
"Requirements files" are files containing a list of items to be installed using pip install like so:
$ pip install -r requirements.txt
In our case we use the requirements.txt file in the setup.py with setuptools to install dependencies.
The myproject/MANIFEST.in includes additional files to the package.
include Authors include README.rst include LICENSE include requirements.txt
import os try: from setuptools import setup from setuptools import find_packages except Exception as e: print("Requires 'setuptools'") print(" pip install setuptools") exit() config = { "name": "myproject", "version": "0.0.0", "author": "Christiaan F Rademan", "author_email": "chris@fwiw.co.za", "description": "MyProject Package Example", "license": "BSD 3-Clause", "keywords": "another example", "url": "http://www.fwiw.co.za", "packages": find_packages(), "include_package_data": True, "classifiers": [ "Topic :: Software Development :: Libraries :: Application Frameworks", "Environment :: Other Environment", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: POSIX :: Linux", "Programming Language :: Python", "Programming Language :: Python :: 2.7" ] } # allow setup.py to be run from any path os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) if os.path.exists(os.path.join(os.path.dirname(__file__), 'requirements.txt')): with open(os.path.join(os.path.dirname(__file__), 'requirements.txt')) as x: requirements = x.read().splitlines() else: requirements = [] with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as x: readme = x.read() print("%s %s\n" % (config['name'])) setup( install_requires=requirements, long_description=readme, **config )
You can use setup.py to register your project on PyPI which is explained later or use it to remove, install your package.
$ python setup.py install
will install the package
$ python setup.py develop
The develop will not install the package but it will create a .egg-link in the deployment directory back to the project source code directory.
So it's like installing but instead of copying to the site-packages it adds a symbolic link (the .egg-link acts as a multiplatform symbolic link).
That way you can edit the source code and see the changes directly without having to reinstall every time that you make a little change. This is useful when you are the developer of that project hence the name develop.
This tells PyPI where your README file is.
[metadata] description-file = README.rst
This file will contain whichver license you want your code to have. I tend to use the BSD 3-Clause license.
From the official website:
PyPI — the Python Package Index
The Python Package Index is a repository of software for the Python programming language.
Upload your code on PyPI. It's a big list of python packages that you absolutely must submit your package to for it to be easily one-line installable.
On PyPI Live and also on PyPI Test, you must create an account in order to be able to upload your code. I recommend using the same email/password for both accounts, just to make your life easier when it comes time to push.
[distutils] index-servers = pypi pypitest [pypi] repository=https://pypi.python.org/pypi username=your_username [pypitest] repository=https://testpypi.python.org/pypi username=your_username
This will attempt to register your package against PyPI's test server, just to make sure you've set up everything correctly.
$ python setup.py register -r pypitest
Now upload your package
$ python setup.py sdist upload -r pypitest
Simply run above commands again and replace pypitest with pypi
If you receive an error TypeError: cannot concatenate 'str' and 'NoneType' objects this is a known bug. Its because the upload is not prompting for the password.
To work around this register and upload at the same time like so:
$ python setup.py sdist register -r pypi upload -r pypi
I recently had to build some filters for implementations and will be sharing them. The goal here is to provide an up-to-date example of a strong protection filtering for both IPv4 and IPV6 and to the address topic of why filters are required.
The topic of router security is fairly complex. So much so that the IETF has an informational RFC 6192 produced to outline best practices. The RFC includes examples for both IOS- and Junos based products.
Modern routers have the forwarding plane separated from the control plane and can forward millions+ of packets per second with ease. However that does not mean the control plane can handle those volumes. If the control plane is over-loaded, it will not able to send or receive routing protocol messages and other important control plane packets in a timely manner such as keep-alives. As a consequence loss of routing protocol adjacency can disrupt traffic flow though the forwarding plane.
Juniper carrier routers packet forwarding happens completely in hardware on the forwarding plane. The router consists of: a routing engine where all the protocols run and forwarding plane (PFE) which receives updates from the RE and programs forwarding functionality.
Since the Routing Engine does not handle packet forwarding its processing cannot be overwhelmed by packets that are supposed to be forwarded.
Firewall filters and policers in JunOS can be used to mitigate certain types of bad traffic that are destined to the router.
A form of denial of service attack on the control plane of routing equipment can lead to the scenario describe above.
There are many ways to protect your router and one of them not included in this post is filtering and policing on broadcast, multicast and unknown traffic. This known as a BUM filter that I may share in another post for Layer2 related networking.
Lastly in addition the Trio-based MX routers have additional DDoS detection features, which is for another post. However the filters provided is the required to be used in combination with other mechanisms to secure your infrastructure.
ARP request packets are sent to the broadcast MAC addresses while ARP replies are sent to the requested source mac. Improper configuration in the network causing broadcast storms could result in flooding of ARP packets to the routing engine. This could also be possible that a port receives lots of ARP requests and reply packets as part of DOS attack. Without protection these packets will all be sent to the routing engine.
By default Juniper routers have a policer for ARP packets that is shared by all interfaces on a line-card and the rate limits the aggregate ARP traffic to a value of 150Kbit/s.
The above default policer applied to ARP packets can be modified using hidden cli commands
firewall { arp-bandwidth-limit 32k; arp-burst-size-limit 2k; }
Below is more aggressive configuration that can be applied on a per port basis. Its better in since one port being flooded does not impact the aggregate ports on the same line card.
groups { PROTECT-ARP { interfaces { <*> { unit <*> { family inet { policer { arp ARP; } } } } } firewall { policer ARP { if-exceeding { bandwidth-limit 8k; burst-size-limit 1501; } then discard; } } } } firewall { apply-groups [ PROTECT-ARP ]; }
Note it could be applied either under physical for all logical interfaces or just under a specific logical interface using apply-groups PROTECT-ARP
Example of applying the above ARP policing to specific interface
interfaces { ge-0/0/0 { apply-groups PROTECT-ARP; description "NAP-AFRICA PEERING EXCHANGE"; unit 0 { family inet { filter { input-list [ RFC1918 MARTIANS BAD-PORTS ACCEPT ]; output-list [ RFC1918 MARTIANS BAD-PORTS ACCEPT ]; } address 196.46.25.100/24; } } } }
The protection filter both for both IPV4 and IPV6 is combined within a simple apply-group to guard against resource depletion denial of service attacks and securing the access to specific protocols using filters. Using apply-groups the filters automatically are updated based on the configuration. For example if you add another BGP neighbor you do not have to add it to any specific prefix list.
However its required to specify core interfaces and mpls loopbacks and prefixes that do have access to the system via SSH or TELNET.
MPLS Loopbacks is used by unicast tcp LDP sessions for example.
groups { SECURE-RE { interfaces { lo0 { unit <*> { family inet { filter { input SECURE-RE4; } } family inet6 { filter { input SECURE-RE6; } } } } } policy-options { prefix-list RFC1918 { 10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16; } prefix-list BGP-NEIGHBORS { apply-path "protocols bgp group <*> neighbor <*>"; } prefix-list NTP-PEERS { apply-path "system ntp peer <*>"; } prefix-list NTP-SERVER { apply-path "system ntp server <*>"; } prefix-list NTP-BOOT-SERVER { apply-path "system ntp boot-server <*>"; } prefix-list DNS-SERVERS { apply-path "system name-server <*>"; } prefix-list INTERFACES-IPV4 { apply-path "interfaces <*> unit <*> family inet address <*>"; } prefix-list LOOPBACKS-IPV4 { apply-path "interfaces lo0 unit <*> family inet address <*>"; } prefix-list SNMP-CLIENT-LISTS { apply-path "snmp client-list <*> <*>"; } prefix-list SNMP-COMMUNITY-CLIENTS { apply-path "snmp community <*> clients <*>"; } prefix-list INTERFACES-IPV6 { apply-path "interfaces <*> unit <*> family inet6 address <*>"; } prefix-list LOOPBACKS-IPV6 { apply-path "interfaces lo0 unit <*> family inet6 address <*>"; } } firewall { family inet { filter SECURE-RE4 { term FIRST-FRAGEMENT { from { first-fragment; } then { discard; } } term IS-FRAGMENT { from { is-fragment; } then { discard; } } term SYN-FLOOD { from { protocol tcp; tcp-flags "(syn & !ack) | fin | rst "; } then { policer TCP-INIT; next term; } } term RSVP { from { source-prefix-list { INTERFACES-IPV4; MPLS-LOOPBACKS; } protocol rsvp; interface-set CORE; } then accept; } term IP-OPTIONS { from { ip-options any; } then { discard; } } term SSH-TELNET { from { source-prefix-list { SSH-TELNET4; } protocol tcp; destination-port [ ssh telnet ]; } then accept; } term SSH-TELNET-OUT { from { source-prefix-list { SSH-TELNET4; } protocol tcp; source-port [ ssh telnet ]; destination-port 1024-65535; } then accept; } term ICMP { from { protocol icmp; icmp-type [ echo-request echo-reply unreachable time-exceeded source-quench timestamp timestamp-reply info-request info-reply ]; } then { policer ICMP; accept; } } term TRACEROUTE { from { destination-prefix-list { INTERFACES-IPV4; } protocol udp; ttl 1; destination-port 33435-33450; } then { policer TRACEROUTE; accept; } } term DNS { from { source-prefix-list { DNS-SERVERS; } destination-prefix-list { INTERFACES-IPV4; } protocol udp; source-port domain; } then { policer DNS; accept; } } term NTP { from { source-prefix-list { NTP-SERVER; NTP-PEERS; NTP-BOOT-SERVER; LOOPBACKS-IPV4; } destination-prefix-list { INTERFACES-IPV4; } protocol udp; destination-port ntp; } then { policer NTP; accept; } } term NTP-LOCAL { from { source-prefix-list { LOOPBACKS-IPV4; } destination-prefix-list { INTERFACES-IPV4; } protocol udp; source-port ntp; } then { policer NTP; accept; } } term SNMP { from { source-prefix-list { SNMP-CLIENT-LISTS; SNMP-COMMUNITY-CLIENTS; } destination-prefix-list { INTERFACES-IPV4; } protocol udp; destination-port snmp; } then { policer SNMP; accept; } } term OSPF { from { destination-address { 224.0.0.5/32; 224.0.0.6/32; } source-prefix-list { INTERFACES-IPV4; } destination-prefix-list { INTERFACES-IPV4; } protocol ospf; interface-set CORE; } then accept; } term BGP-IN { from { source-prefix-list { BGP-NEIGHBORS; } protocol tcp; destination-port bgp; } then accept; } term BGP-OUT { from { source-prefix-list { BGP-NEIGHBORS; } protocol tcp; source-port bgp; destination-port 1024-65535; } then accept; } term VRRP { from { destination-address { 224.0.0.18/32; } source-prefix-list { INTERFACES-IPV4; } protocol vrrp; } then { policer VRRP; accept; } } term LDP { from { destination-address { 224.0.0.2/32; } source-prefix-list { INTERFACES-IPV4; MPLS-LOOPBACKS; } protocol udp; destination-port ldp; interface-set CORE; } then accept; } term LDP-UNICAST { from { source-prefix-list { INTERFACES-IPV4; MPLS-LOOPBACKS; } destination-prefix-list { INTERFACES-IPV4; MPLS-LOOPBACKS; } protocol tcp; port ldp; interface-set CORE; } then accept; } term TLDP-DISCOVER { from { destination-prefix-list { INTERFACES-IPV4; MPLS-LOOPBACKS; } protocol udp; destination-port ldp; interface-set CORE; } then accept; } term LDP-IGMP { from { destination-address { 224.0.0.2/32; } source-prefix-list { INTERFACES-IPV4; MPLS-LOOPBACKS; } protocol igmp; interface-set CORE; } then accept; } term OTHER { then { log; discard; } } } } family inet6 { filter SECURE-RE6 { /* Beware - VRRPv3 with authentication or OSPFv3 with Authentication enabled may use AH/ESP */ term DISCARD-EXTENSION-HEADERS { from { next-header [ ah dstopts egp esp fragment gre icmp igmp ipip ipv6 no-next-header routing rsvp sctp ]; } then discard; } term SYN-FLOOD { from { next-header tcp; tcp-flags "(syn & !ack) | fin | rst "; } then { policer TCP-INIT; next term; } } term NEIGBOR-DISCOVERY { from { next-header icmpv6; icmp-type 133-136; } then { policer ICMP; accept; } } term INVERSE-NEIGHBOR-DISCOVERY { from { next-header icmpv6; icmp-type 141-142; } then { policer ICMP; accept; } } term ICMP-DEST-UNREACHABLE { from { next-header icmpv6; icmp-type destination-unreachable; } then { policer ICMP; accept; } } term ICMP-PACKET-TOO-BIG { from { next-header icmpv6; icmp-type packet-too-big; } then { policer ICMP; accept; } } term ICMP-TIME-EXCEEEDED { from { next-header icmpv6; icmp-type time-exceeded; icmp-code 0; } then { policer ICMP; accept; } } term ICMP-ECHO-REPLY { from { next-header icmpv6; icmp-type echo-reply; } then { policer ICMP; accept; } } term ICMP-ECHO-REQUEST { from { next-header icmpv6; icmp-type echo-request; } then { policer ICMP; accept; } } term ICMP-PARAMTER-PROBLEM { from { next-header icmpv6; icmp-type parameter-problem; icmp-code [ 1 2 ]; } then { policer ICMP; accept; } } term DNS { from { source-prefix-list { DNS-SERVERS; } destination-prefix-list { INTERFACES-IPV6; } next-header [ udp tcp ]; source-port domain; } then { policer DNS; accept; } } term NTP { from { source-prefix-list { NTP-BOOT-SERVER; NTP-PEERS; LOOPBACKS-IPV6; } destination-prefix-list { INTERFACES-IPV6; } next-header udp; destination-port ntp; } then { policer NTP; accept; } } term NTP-LOCAL { from { source-prefix-list { LOOPBACKS-IPV6; } destination-prefix-list { INTERFACES-IPV6; } next-header udp; source-port ntp; } then { policer NTP; accept; } } term SSH-TELNET { from { source-prefix-list { SSH-TELNET6; } next-header tcp; destination-port [ ssh telnet ]; } then accept; } term TRACEROUTE { from { destination-prefix-list { INTERFACES-IPV6; } next-header udp; destination-port 33435-33450; hop-limit 1; } then { policer TRACEROUTE; accept; } } term OSPF3 { from { source-address { fe80::/64; } next-header ospf; interface-set CORE; } then accept; } term BGP-IN { from { source-prefix-list { BGP-NEIGHBORS; } next-header tcp; destination-port bgp; } then accept; } term BGP-OUT { from { source-prefix-list { BGP-NEIGHBORS; } next-header tcp; source-port bgp; destination-port 1024-65535; } then accept; } term OTHER { then discard; } } } policer TCP-INIT { if-exceeding { bandwidth-limit 500k; burst-size-limit 1501; } then discard; } policer ICMP { if-exceeding { bandwidth-limit 2m; burst-size-limit 1501; } then discard; } policer TRACEROUTE { if-exceeding { bandwidth-limit 500k; burst-size-limit 1501; } then discard; } policer DNS { if-exceeding { bandwidth-limit 500k; burst-size-limit 1501; } then discard; } policer NTP { if-exceeding { bandwidth-limit 500k; burst-size-limit 1501; } then discard; } policer SNMP { if-exceeding { bandwidth-limit 500k; burst-size-limit 1501; } then discard; } policer VRRP { if-exceeding { bandwidth-limit 500k; burst-size-limit 1501; } then discard; } policer NON-IP { if-exceeding { bandwidth-limit 250k; burst-size-limit 1501; } then discard; } } } }
Example of applying SECURE-RE Filter
apply-groups [ SECURE-RE ]; firewall { interface-set CORE { et-0/0/0.0; et-0/0/1.0; } } policy-options { prefix-list SSH-TELNET4 { 127.0.0.1/32; } prefix-list MPLS-LOOPBACKS { 10.10.10.0/24 } prefix-list SSH-TELNET6 { ::1/128; } }