9

Vyos – Site to site VPN using VTI and OSPF

Hey! So today we will be challenging setup of vyos site-to-site VPN. In theory there is nothing really difficult about that one – its just choosing the right options.

What I would really would like to highlight here which I believe is quite useful ( although not always possible to achieve ) is to use VTI ( Virtual Tunnel Interface ) instead of local/remote prefixes ( more reading here ). So let’s get to do it 🙂 All of these commands will be part of single commit.

First we tackle the virtual interface

set interfaces vti vti0 address 10.1.0.1/32
set interfaces vti vti0 description 'VPN_VTI0'

Of course description is optional however I like the system to be well described so other people can also benefit from understanding quickly what and why is it.

Next I fill out phase 1 and phase 2 settings. And here I cannot help much as it will differ per endpoint you are setting your vpn with. So treat this only as point of reference

# Phase 2 
set vpn ipsec esp-group ESP-Default compression 'disable' 
set vpn ipsec esp-group ESP-Default lifetime '3600' 
set vpn ipsec esp-group ESP-Default mode 'tunnel' 
set vpn ipsec esp-group ESP-Default pfs 'dh-group2' 
set vpn ipsec esp-group ESP-Default proposal 1 encryption '3des' 
set vpn ipsec esp-group ESP-Default proposal 1 hash 'sha1' 

# Phase 1 
set vpn ipsec ike-group IKE-Default dead-peer-detection action 'clear' 
set vpn ipsec ike-group IKE-Default dead-peer-detection interval '30' 
set vpn ipsec ike-group IKE-Default dead-peer-detection timeout '90' 
set vpn ipsec ike-group IKE-Default ikev2-reauth 'no' 
set vpn ipsec ike-group IKE-Default key-exchange 'ikev1' 
set vpn ipsec ike-group IKE-Default lifetime '86400' 
set vpn ipsec ike-group IKE-Default proposal 1 dh-group '2' 
set vpn ipsec ike-group IKE-Default proposal 1 encryption 'aes256' 
set vpn ipsec ike-group IKE-Default proposal 1 hash 'sha256'

 

Cool – so we got the base – now we need to define which interface will handle our VPN traffic

set vpn ipsec ipsec-interfaces interface 'eth1' 
set vpn ipsec logging log-modes 'all'

 

And then I move to configuring site-to-site vpn

# Setup the site-2-site config
set vpn ipsec site-to-site peer <remote-IP-address> authentication id '<local-WAN-IP-address>' 
set vpn ipsec site-to-site peer <remote-IP-address> authentication mode 'pre-shared-secret' 
set vpn ipsec site-to-site peer <remote-IP-address> authentication pre-shared-secret 'this-Of-course-Is-Some-paaaassshpraseeee' 
set vpn ipsec site-to-site peer <remote-IP-address> connection-type 'initiate' 
set vpn ipsec site-to-site peer <remote-IP-address> default-esp-group 'ESP-Default' 
set vpn ipsec site-to-site peer <remote-IP-address> ike-group 'IKE-Default' 
set vpn ipsec site-to-site peer <remote-IP-address> ikev2-reauth 'inherit' 
set vpn ipsec site-to-site peer <remote-IP-address> local-address '<local-WAN-IP-address>' 

Once done we need to associate our VTI interface with this site to site VPN. This is done by issuing the following

# Make use of our VTI interface
set vpn ipsec site-to-site peer <remote-IP-address> vti bind vti1
set vpn ipsec site-to-site peer <remote-IP-address> vti esp-group ESP-Default

 

Cool – easy wasn’t ? 🙂 Now we can configure OSPF. I did mine this way

set protocols ospf parameters router-id <remote-IP-address>
set protocols ospf area 0.0.0.0 network 192.168.1.0/24
set protocols ospf area 0.0.0.0 network 192.168.2.0/24
set interfaces vti vti0 ip ospf network point-to-point

 

Full config as usual available in github

 

 

Any experience on challenges ? Maybe better ways ? Post in comments!

2

Logstash – Filtering Vyos syslog data

logstash-logoHey , So in last days/weeks 🙂 I work quite a lot with ELK stack. Especially in getting data from my systems into Elastic. There would not be any problem if not the fact that default parsing did not quite do work. But what would be IT life without challenges ?

So in this post I will explain in short how I have overcome this problem. And I’m sure you would be able to use this or event make it better.

We will look into following:

* Incoming raw data

* Creating filter

* Enjoying results

 

Incoming raw data:

So you got your vyos box doing the hard work on the edge of your network. And now you would like to have control when someone is knocking to your door or to find root cause when troubleshooting firewall rules.

Example of incoming data from my box looks similar to the following :

<4>Dec  6 01:36:00 myfwname kernel: [465183.670329] 
[internet_local-default-D]IN=eth2 OUT= 
MAC=00:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:00 
SRC=5.6.7.8 DST=1.2.3.4 LEN=64 TOS=0x00 
PREC=0x00 TTL=56 ID=10434 DF PROTO=TCP 
SPT=51790 DPT=80 WINDOW=65535 RES=0x00 SYN URGP=0

and if we just apply basic syslog filtering it will not give out all required fields. The problem we challenge here is we need to get out internet rule. Then following that we can see use case for key value filter.

 

Creating filter:

So time has come to use some magical skills of creating configuration for Logstash filter. I would like to put stress that using different approaches can have impact on performance. Both negative and positive. As yet I’m getting familiar with Logstash this might not be the best solution but I will definitely explore this.

You will notice that my filters use conditional statements so I do not process data unnecessary. In my case vyoss traffic is tagged as syslog and contains specific string in the message.

So without further bubbling … We begin with parsing out data from the message that will get for sure extracted.

  if [type] == "syslog" and [message] =~ "myfw" {
    grok {
      break_on_match => false
      match => [
      "message",  "<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: \[(?<syslog_pid>.*?)\] %{GREEDYDATA:syslog_message}",
      "syslog_message", "\[(?<firewall_rule>.*?)\]"
      ]
    }

Points of interest here :

  • Grok filter DOES NOT break on match
  • We do match on message and further on extracted syslog_message to get our firewall rule from [ ]

Next we will do changes on fly to our fields using mutate

    # mutate our values
    mutate {
      add_field => [ "event_type", "firewall" ]
      rename => { "firewall_rule" => "[firewall][rule]" }
      gsub => [ "message", "= ", "=xxx" ]            # Here we remove scenario where this value is empty
    }

Points of interest :

  • I add a field event_type  called firewall so in future I would be able to quickly query for those events.
  • I rename my previous field ( firewall_rule ) to nested field
  • And lastly I use gsub to mitigate problem of missing values in key pair

Once this is done I extract remaining values using kv filter which is configured as follow :

    # Apply key value pair
    kv {
      include_keys => ["SRC","DST","PROTO","IN","MAC","SPT","DPT"]
      field_split => " \[\]"
      add_field => {
        "[firewall][source_address]" => "%{SRC}"
        "[firewall][destination_address]" => "%{DST}"
        "[firewall][protocol]" => "%{PROTO}"
        "[firewall][source_port]" => "%{SPT}"
        "[firewall][destination_port]" => "%{DPT}"
        "[firewall][interface_in]" => "%{IN}"
        "[firewall][mac_address]" => "%{MAC}"
      }
    }

Points of interest :

  • I use include_keys so only fields in array will be extracted ( positive impact on performance )
  • I tried field_split to help out with one of previous challenges but that did not make a lot of difference
  • And lastly I specify my new nested fields for extracted values

 

So thats it! The complete file looks following :

filter {
  if [type] == "syslog" and [message] =~ "vmfw" {
    grok {
      break_on_match => false
      match => [
      "message",  "<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: \[(?<syslog_pid>.*?)\] %{GREEDYDATA:syslog_message}",
      "syslog_message", "\[(?<firewall_rule>.*?)\]"
      ]
    }
    
    # mutate our values
    mutate {
      add_field => [ "event_type", "firewall" ]
      rename => { "firewall_rule" => "[firewall][rule]" }
      gsub => [ "message", "OUT= MAC=", "MAC=" ]            # Here we remove scenario where this value is empty
    }

    # Apply key value pair
    kv {
      include_keys => ["SRC","DST","PROTO","IN","MAC","SPT","DPT"]
      field_split => " \[\]"
      add_field => {
        "[firewall][source_address]" => "%{SRC}"
        "[firewall][destination_address]" => "%{DST}"
        "[firewall][protocol]" => "%{PROTO}"
        "[firewall][source_port]" => "%{SPT}"
        "[firewall][destination_port]" => "%{DPT}"
        "[firewall][interface_in]" => "%{IN}"
        "[firewall][mac_address]" => "%{MAC}"
      }
    }
  }
}

 

Enjoying results:

We now would need to test this if it really works as we expect it to work. For this to check we of course will use Docker

First I will create the afore mentioned config file and name it logstash.conf . Once thats done we bring up container up with the following command :

docker run -d -p 25666:25666 -v "$PWD":/config-dir logstash logstash -f /config-dir/logstash.conf

This creates container for me which I can then test locally. Now for this to work you need input source ( i.e. tcp / udp and stdout i.e. codec ruby )

Then I will split my screen using tmux and will execute request while looking at results from docker logs

Logstash-vyos-local

 

And thats it! You have beautifully working parsing for your vyos box ! If you have any comments / or improvements – feel free to share!

 

 

0

Configure WSMan connectivity on vyos firewall

This is just a quick write up. When working with secure environements it might be necessary to open some firewall ports.  If by anychance you are looking how to do that on vyos firewall below you find details.

Enter configuration mode :

# Enter configuration mode
Config

Create new rule

# Port Group 
set firewall group port-group WSMan port '5985-5986'

# Set the rule
set firewall name some-name rule 666 action 'accept'
set firewall name some-name rule 666 description 'Allow for PowerShell remoting'
set firewall name some-name rule 666 destination group network-group AllNetworks
set firewall name some-name rule 666 destination group port-group 'WSMan'
set firewall name some-name rule 666 protocol 'tcp'
set firewall name some-name rule 666 source group address-group 'my-managemnt-servers'

 

Now above might require short explanation :

  • First we create a port group called WSMAN
  • Then we create rule 666 which will allow for powershell remoting
  • It will be allowed to network group defined in AllNetworks  ( defining it is beyond the scope of this short post so you can always find it in documentation http://vyos.net/wiki/User_Guide )
  • We specify we will allow port group defined earlier (so in our case WsMan ports )
  • Its type of TCP
  • and lastly we say that source of this will be my management servers defined as address group with name my-management-servers ( again 🙂 I will refer you to wiki how to create those )

One you are done with those you need to make sure configuration is commited. This is done by calling the following :

Commit

 

If there are no validation errors just save the config 🙂 so you are not suprised that after reboot it does not work 🙂

save

 

Enjoy securing your networks 🙂