Get last two segment of ip address using Ansible - string

I have a playbook that grabs ip address as below.
---
- hosts: all
tasks:
- debug: var=hostvars[inventory_hostname]['ansible_default_ipv4']['address']
Output:
TASK [debug] *************************************************************************************************************************************************
ok: [mwiwas01] => {
"hostvars[inventory_hostname]['ansible_default_ipv4']['address']": "10.0.12.15"
}
However, I wish to get the last two segments of an ip address i.e only 12.15.
Note: the ip addresses would change on each host hence I m looking for a standard solution that is compatible to work for any given IP version 4.
How can I grab the same from the IP address.

Make use of split function .
- debug: var=hostvars[inventory_hostname]['ansible_default_ipv4']['address'].split(".")[3]+hostvars[inventory_hostname]['ansible_default_ipv4']['address'].split(".")[4]

Related

Defining IP address to a programatically defined VLAN

I am trying to create TAP's programatically, to which i am attaching a VLAN and an IPV4 address.
(using C, linux 5.4.56, on an embedded device)
TAP is created correctly with the regular ioctl's (TUNSETIFF, etc ...)
Then, i am using another set of ioctl's to set the VLAN, IPADDR, NETMASK, FLAGS, etc ... (SIOCGIFFLAGS, SIOCSIFADDR, etc ...).
For example
init_sockaddr_in_str((struct sockaddr_in *) &ifr.ifr_addr, ipv4_addr_str);
if (ioctl(sd, SIOCSIFADDR, &ifr) < 0) {
LOG("ioctl(SIOCGSIFADDR) error: (%s)\n",strerror(errno));
}
for setting the IPaddress, sd being a socket created to access this interface file descriptor.
Let supposet I created tap256 at first, the a VLAN tag 256, and an IPaddress a.b.c.d
The problem i have is that, at linux cli, i can correctly see all these interfaces with
"ip -d a"
but
Only the TAP256 is UP with the address set to IT ... an no VLAN
Another interface has been created (TAP256.256) which is DOWN with the VLAN defined
Of course, i can fix this manually (removing the IP addr from one interface, setting it to the other, etc ... but this is not the preferred option, i really liked it to be done programatically.
Is there something i am doing not right ? or a specific sequence of actions which will lead to my TAP256.256 UP and the correct IP address attached to it ?
Thanks,
Jacques

Logstash (ELK): Enrich IP with hostname (based off a file). - (No direct connect w/ DNS/AD)

Trying to figure out how to enrich the data being ingested (Network Data) Zeek/Suricata. I would like to either show Hostname vice IP, or more preferably add another field for hostname based off the IP address.
Have a file with IP -> Hostnames (CSV) currently could be anything other format if required. Unable to get IP to Hostname with DNS or Active Directory or any other connected means.
I know in Splunk you could do lookup tables, but unsure how to accomplish the same in the ELK stack to view the results in Kibana.
You could do this in logstash using a translate filter, which requires a two-column CSV file (or YML, or JSON). You could try
translate {
source => "[fieldWithIP]"
dictionary_path => "/path/to/mapping.csv"
target => "[fieldForHostname]"
}
this would add a new field called [fieldForHostname] if the value of [fieldWithIP] is found in column 1 of the mapping.csv

fail2ban: if a line matches both failregex and ignoreregex, which one has priority?

What the subject says. I have an user who logs in using SSH through a provider that gives him a dynamic IP from a pool; all of their IPs map to static.hostingprovider.name, but that name doesn't resolve back to the same IP address.
SSH detects this and spits out the message "POSSIBLE BREAK-IN ATTEMPT", which triggers the failregex. I want to add an exception so that, if the connection attempt comes from static.hostingprovider.name, it ignores the warning. If I just add static.hostingprovider.name to the ignoreregex list, will it simply work?
In your jail.local file add this line:
ignoreip = static.hostingprovider.name

Discover linux interface name based on IP address

I have code which search specified IP in linux system:
- name: find IP
set_fact:
ip: "{{ item }}"
with_items: "{{ansible_all_ipv4_addresses}}"
when: "item.startswith('10.')"
And works ok, but I can't find out how to discover interface name based on IP from fact "ip".
Does anybody could give some advice or maybe have some example how to do it?
Ansible provides a list of interfaces in the ansible_interfaces fact. You can use this to iterate over available interfaces, checking each one for a given ip address.
That ends up being trickier than it sounds because you'll need to construct fact names, which means rather than something simple like:
ansible_eth0
You instead need:
hostvars[inventory_hostname]["ansible_%s" % item]
An additional complication is that Ansible divides ip addresses into "primary" (which is ansible_eth0.ipv4.address) and "secondaries" (ansible_eth0.ipv4_secondaries), where the latter is a list of dictionaries with address keys. Assuming that we are iterating with item set to an interface name, we can get the primary address like this:
hostvars[inventory_hostname]["ansible_%s" % item].ipv4.address
But! That will fail for interfaces that don't have an ipv4 address assigned, or that don't have a corresponding ansible_<interface> fact for some reason. So we need to deal gracefully with that situation:
(hostvars[inventory_hostname]["ansible_%s" % item]|default({}).get('ipv4', {}).get('address')
This uses the default filter to ensure that we start with a dictionary, and then we use a few levels of Python's .get(key, default) method.
Checking against the secondary addresses is similar but requires that we use the map filter because ipv4_secondaries gives us a list of dictionaries and what we really want is a list of addresses (so that we can check if our target address is in that list):
((hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4_secondaries'))|map(attribute='address')|list
Putting it all together:
- hosts: localhost
vars:
target_address: 192.168.122.1
tasks:
- set_fact:
target_interface: "{{ item }}"
when: >
(hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4', {}).get('address') == target_address
or
target_address in ((hostvars[inventory_hostname]['ansible_%s' % item]|default({}))
.get('ipv4_secondaries'))|map(attribute='address')|list
with_items:
- "{{ ansible_interfaces }}"
- debug:
msg: >-
found interface {{ target_interface }}
with address {{ target_address }}
If I run this on my system, the playbook run concludes with:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "found interface virbr0 with address 192.168.24.1"
}
If I run:
ansible-playbook playbook.yml -e target_address=192.168.1.75
I get:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "found interface eth0 with address 192.168.1.75"
}
As you can see from the above, this isn't exactly the sort of task that Ansible is meant for. You would probably be better off stuffing all this logic into an Ansible module so that you could use Python (or some other language) to perform the lookup in a more graceful fashion.
Update
Here is a module-based solution to the same problem.

How to make rule trigger on DNS rdata/IP address?

I currently have the following DNS Query Alert rule set up in Suricata (for test purposes):
alert dns any any -> any any (msg:”Test dns_query option”; dns_query; content:”google”; nocase; sid:1;)
Which is triggered when it captures DNS events which contain the word "google", such as in this packet:
{"timestamp":"2017-06-08T15:58:59.907085+0000","flow_id":1798294020028434,"in_iface":"ens33","event_type":"dns","src_ip":"172.16.10.132","src_port":53,"dest_ip":"192.168.160.140","dest_port":52385,"proto":"UDP","dns":{"type":"answer","id":57334,"rcode":"NOERROR","rrname":"www.google.com","rrtype":"A","ttl":300,"rdata":"172.217.12.164"}}
However, instead of searching for resource record names that contain "google", I want to use this same kind of alert to trigger on IP addresses that resolve to loopback, as is the case with the following packet (Notice the rdata field):
{"timestamp":"2017-06-08T15:59:37.120927+0000","flow_id":36683121284050,"in_iface":"ens33","event_type":"dns","src_ip":"172.16.10.132","src_port":53,"dest_ip":"192.168.160.140","dest_port":62260,"proto":"UDP","dns":{"type":"answer","id":53553,"rcode":"NOERROR","rrname":"outlook1.us","rrtype":"A","ttl":120,"rdata":"127.0.0.1"}}
As I have noticed, the contentsection of a Suricata rule searches only for a string.
My current rule triggers on a text match with the rrname/domain, how would I make it so that the rule triggers on rdata/IP address?
p.s.
Just out of curiosity I tried replacing the "google" in the content section of my alert with "127.0.0.1" and that didn't work either, as expected.
The ip address is just a 32 bit number. In the rule the IP should be represented as a hex value and not a string, for purposes of efficiency and saving bandwidth (a string will be 8+ bytes as opposed to 4 bytes).
Here is my final Suricata rule to alert whenever somebody gets sent to loopback on my network:
alert dns any any -> any any (msg:"BLACKLISTED DOMAIN"; content:"|7F 00 00 01|"; sid:1;)

Resources