Friday, April 29, 2016

My Introduction to firewallD

WARNING:

  1. When I say My Introduction, I do not mean I am trying to introduce you to firewallD. I really mean this is the first time I had to properly deal with it. I wish this story would involve robots, but it is not that exciting

  2. You should not follow this blindly as a guide. I screwed it up and documented it here. Read it first and see what I did wrong and why.

So I am building an apache webserver on a Linux box (Red Hat Enterprise Server 7.2 if you are curious, but there is nothing stopping the gist of my story working on any Linux distro using systemd and, more specifically, firewallD) and want to limit the number of hosts that can access it to one, which happens to have 192.168.79.13 as its IP.

In the golden days...

If we were to use dear ol' pedestrian iptables, one way to create the rules would be

iptables -I INPUT -s '192.168.79.13/32' -m state --state NEW \
   -m tcp -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -s '192.168.79.13/32' -m state --state NEW \
   -m tcp -p tcp --dport 443 -j ACCEPT

and then check if it has been loaded using

iptables -L -n

At this point we might have decided we really should have also told it to apply the rule to only a specific interface or IP (we might be listening to many IPs on the same interface). So we would adjust it as needed until we are satisfied. And, once satisfied it works, save it using

service iptables save

Modern Times

So far so good. But in Red Hat 7 and CentOS 7 as a result, iptables save is no longer an available command. firewallD should be used instead, which is amusing since it is but a front end to iptables. I guess the point is that if iptables is replaced you would still be able to use firewallD to control whatever comes next; in other words, it is an abstraction layer.

But, I digress. Bottom line is we need to figure out how to use firewallD. First thing is that we will be using firewall-cmd to talk to it. Next is that it allows to create separate firewall zones (same idea as the Windows firewall zones for the Microsoft crowd amongst you) which define the interface and possibly IPs it is associated with and which services and rules are supposed to do what there. And, yes, that last sentence was a mouthful, so we shall begin by seeing which zone we are using.

[user@webtest httpd]$ sudo firewall-cmd --get-default-zone
public
[user@webtest httpd]$

I guess that makes sense since this is a pretty much out-of-the-box install; we are still customizing it. But, which zones are in use?

[user@webtest httpd]$ sudo firewall-cmd --get-active-zones
public
  interfaces: eth0
[user@webtest httpd]$

So, the only active zone is the default one, which is being applied to eth0. What can you tell me about the public zone?

[user@webtest httpd]$ sudo firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

[user@webtest httpd]$

I knew about ssh service (sshd) -- that is how I am connected to it -- but I did not realize it actually has a dhcpv6 client. How about ports in use?

[user@webtest httpd]$ sudo firewall-cmd --zone=public --list-ports
[user@webtest httpd]$

Hmmm, nothing? But sshd uses port 22 by default (which is how it is set right now); shouldn't it show up? Well, like Windows' firewall you can specify a service or just a port. If you do the former, its port is not listed. I wonder if it is just satisfied the ssh service is on and relies on it to know which port it is using; this sounds like something worthwhile to test later. Talking about services, which ones firewallD knows of, be them running or not?

[user@webtest httpd]$ sudo firewall-cmd --get-services
RH-Satellite-6 amanda-client bacula bacula-client dhcp dhcpv6 dhcpv6-client 
dns freeipa-ldap freeipa-ldaps freeipa-replication ftp high-availability http 
https imaps ipp ipp-client ipsec iscsi-target kerberos kpasswd ldap ldaps 
libvirt libvirt-tls mdns mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy 
pmwebapi pmwebapis pop3s postgresql proxy-dhcp radius rpc-bind rsyncd samba 
samba-client smtp ssh telnet tftp tftp-client transmission-client vdsm 
vnc-server wbem-https
[user@webtest httpd]$

It even knows about telnet! Not that it is even installed here, which means firewallD has some kind of configuration file somewhere listing all the services it should be aware of. Which means you can add/subtract services to this list... or it ends up overwritten during an upgrade. One of the two, right?

So we created the firewall zone. How does it look like? It is actually a xml file; here's the one for the public zone as it stands right now in this conversation:

[user@webtest httpd]$ sudo cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other 
computers on networks to not harm your computer. Only selected incoming 
connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
</zone>
[user@webtest httpd]$

I think we have an idea of the beast.

Houston, we have a problem

So, let's say we want to allow access to our webserver on port 80. We can do something like

firewall-cmd --zone=public --add-port=80/tcp --permanent

or

firewall-cmd --zone=public --add-service=http --permanent

right? Er, not quite. Let me show what I mean: after we run one of those commands (I picked the service one) we should always check if the zone was updated.

[user@webtest httpd]$ sudo firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

[user@webtest httpd]$

But yet, it is in the file!

[user@webtest httpd]$ sudo cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other 
computers on networks to not harm your computer. Only selected incoming 
connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <service name="http"/>
</zone>
[user@webtest httpd]$

What is going on? Short version: user error. Long version: --permanent means save to file only. It does not affect the running version. If you want to turn it on, you need to restart firewalld.

[user@webtest httpd]$ sudo systemctl restart firewalld
[user@webtest httpd]$

Another alternative is not to use --permanent, as in

firewall-cmd --zone=public --add-service=http

That will commit the change immediately. If you reboot it is lost, so it is a good way to test it. And then once you are ready to commit, you can then do

firewall-cmd --runtime-to-permanent

which as the name implies saves the running firewall to the appropriate zone files. In any case, here is the outcome:

[user@webtest httpd]$ sudo firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client httpd ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

[user@webtest httpd]$

If you want to remove that very rule, you can do it by

firewall-cmd --zone=public --remove-service=httpd

Back to the iptables example

Do you remember it? No? Let me put it here

iptables -I INPUT -s '192.168.79.13/32' -m state --state NEW \
   -m tcp -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -s '192.168.79.13/32' -m state --state NEW \
   -m tcp -p tcp --dport 443 -j ACCEPT

The key here is not we are specifying the ports, but that we want to specify the IP traffic is coming from. In the firewalld universe that requires a rich rule. Here is what I am using:

firewall-cmd --zone=public --add-rich-rule="rule family="ipv4" \
    source address="192.168.79.13/32" service name="http" accept"
firewall-cmd --zone=public --add-rich-rule="rule family="ipv4" \
    source address="192.168.79.13/32" service name="https" accept"

it should behave the very same way as the iptables entries. But, let's see how it looks like in runtime

[user@webtest httpd]$ sudo firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" source address="192.168.79.13/32" service 
name="https" accept
        rule family="ipv4" source address="192.168.79.13/32" service 
name="http" accept
[user@webtest httpd]$

And, after we are satisfied and committed it, in the zone file

[user@webtest httpd]$ sudo cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other 
computers on networks to not harm your computer. Only selected incoming 
connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <rule family="ipv4">
    <source address="192.168.79.13/32"/>
    <service name="https"/>
    <accept/>
  </rule>
  <rule family="ipv4">
    <source address="192.168.79.13/32"/>
    <service name="http"/>
    <accept/>
  </rule>
</zone>
[user@webtest httpd]$

References

Thursday, April 28, 2016

Where's my video card (Command line)?

This will be a quick article, I promise!

Here's is something that started when I was building a new VM. I wanted this VM in question to, as you probably have guessed, be able to access the video card using PCI passthrough. But I think some of you can find more interesting applications for this.

Since I cannot use the real machine, let's use a surrogate: an ASRock Z77 Extreme4-based computer (ok, I booted it off a liveCD; deal with it) which should has a Xeon E3-1200 onboard video.

Out good old friend lspci tells us that (I just grabbed the line that matched the name of the video controlelr)

00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09)

Can lspci provide us with more details? It actually can if we use option -s. Let's see what the man page tells us:

-s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]
              Show  only devices in the specified domain (in case your machine
              has several host bridges, they can either  share  a  common  bus
              number  space  or  each  of them can address a PCI domain of its
              own; domains are numbered from 0 to ffff), bus (0 to  ff),  slot
              (0  to  1f) and function (0 to 7).  Each component of the device
              address can be omitted or set to "*", both meaning "any  value".
              All  numbers  are  hexadecimal.  E.g., "0:" means all devices on
              bus 0, "0" means all functions of device 0  on  any  bus,  "0.3"
              selects  third  function of device 0 on all buses and ".4" shows
              only the fourth function of each device.

So, 00:02.0 means:

  • 00 - Bus 0
  • 02 - Slot 2
  • 0 - All functions. Are there other functions I can see? I have not found, but that could be only for this guy
Then we rerun lspci with the above arguments:

[user@desktop ~]$ lspci -s 00:02.0 -v
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09) (prog-if 00 [VGA controller])
        Subsystem: ASRock Incorporation Motherboard
        Flags: bus master, fast devsel, latency 0, IRQ 29
        Memory at f7400000 (64-bit, non-prefetchable) [size=4M]
        Memory at e0000000 (64-bit, prefetchable) [size=256M]
        I/O ports at f000 [size=64]
        Expansion ROM at <unassigned> [disabled]
        Capabilities: <access denied>
        Kernel driver in use: i915
        Kernel modules: i915


[user@desktop ~]$ 

How about cranking up the verbose mode while we are at it?

[user@desktop ~]$ lspci -s 00:02.0 -vvv
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09) (prog-if 00 [VGA controller])
        Subsystem: ASRock Incorporation Motherboard
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 29
        Region 0: Memory at f7400000 (64-bit, non-prefetchable) [size=4M]
        Region 2: Memory at e0000000 (64-bit, prefetchable) [size=256M]
        Region 4: I/O ports at f000 [size=64]
        Expansion ROM at <unassigned> [disabled]
        Capabilities: <access denied>
        Kernel driver in use: i915
        Kernel modules: i915

[user@desktop ~]$

I feel like I am being denied some info. Time to become root and shout at it surrender your secrets to me!

[root@desktop ~]# lspci -s 00:02.0 -vvv
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09) (prog-if 00 [VGA controller])
        Subsystem: ASRock Incorporation Motherboard
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 29
        Region 0: Memory at f7400000 (64-bit, non-prefetchable) [size=4M]
        Region 2: Memory at e0000000 (64-bit, prefetchable) [size=256M]
        Region 4: I/O ports at f000 [size=64]
        Expansion ROM at <unassigned> [disabled]
        Capabilities: [90] MSI: Enable+ Count=1/1 Maskable- 64bit-
                Address: fee0f00c  Data: 4191
        Capabilities: [d0] Power Management version 2
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
        Capabilities: [a4] PCI Advanced Features
                AFCap: TP+ FLR+
                AFCtrl: FLR-
                AFStatus: TP-
        Kernel driver in use: i915
        Kernel modules: i915

You have new mail in /var/spool/mail/root
[root@desktop ~]#

Now we get some more interesting info (look at the Control and Status lines).

Sunday, April 17, 2016

Badlock Microsoft

It is 5 days since this happened but I am not over that. So, today I am doing some venting.

So on April 12, after weeks of hype-building, Microsoft finally announced details about the Badlock vulnerability. Before that, all we knew (just ask Naked Security) was its cute name and Heartbleed-derived logo. Yes I put it on the right since I do not want to focus on it. And then the stampede to patch servers -- both Windows and those running Samba -- began.

Before someone gets excited, beginning on OSX 10.7 Apple decided to use its own SMB stack, smbx, which should not be affected. Of course, "should" is an interesting word.

Back to the topic, Badlock in the Microsoft website is known as MS16-047 and consists of

  • KB3148527 for more detailed (?) description of the issue and
  • KB3149090 for the patch itself.

I too had to worry about patching Windows servers.

The machine in question is a Windows Server 2008 box. Yes, I know, it is ancient (I was going to mention I know places still running Windows 2003 server and XP desktops, but I better not scare anyone) but still supported by Windows. And, that is what I had to play with. More importantly, that is the one I remembered to do a screen capture, which is shown here.

As some of you know, I do not like clickety-click interfaces unless they let me run and query them using scripts. And I do not know how to do that in for that window, so here is how it looks like from the command line (in case you want to check whether a specific patch has been installed):

wmic qfe list brief | Select-String -pattern "3149090"
Security Update               KB3149090               DR-ZAIUS\Administrator  4/12/2016                                       

OK, it does not show all the info on the windows since I used the brief option, but it does verify said KB has been applied. So now we can go back to the dialog box. It shows a url, http://support.microsoft.com/kb/3149090/. When I applied said patch on April 12, the Badlock day, it went nowhere. As in page not found. Now it resolves to https://support.microsoft.com/en-us/kb/3149090

For some of you this might not sound a problem, but they have been announcing that April 12 was the Badlock Day for how long? And when it comes around you can't even go to the site and download the patch (using Windows upgrade worked tough)? This feels a bit like amateur hour to me. Microsoft, you had lots of time to get it ready, so no excuse.

Ok, venting is complete. Back to the normal programming.

Fun Fact

Now, if we jump into our DeLorean (or a more environmentally conscious time machine), we can go back to 2009 and find an interesting post from Microsoft called Credential Relaying Attacks on Integrated Windows Authentication. I could go and make the case that the issues it raises are suspiciously similar to those in badlock, but I would rather not. Instead, I would suggest you to take a look at the suggestions; they might be useful.