Showing posts with label DNS. Show all posts
Showing posts with label DNS. Show all posts

Friday, April 14, 2017

Projects

A project is a great Solaris facility essential to network-wide system architecture and administration. In essence it's rather simple but in general it's less-known or frequently misunderstood or underestimated by many engineers, unfortunately. Later on defining projects, in order to take full advantage of them (and their tasks) it's necessary to enable extended accounting, but that will be a topic for a later post.

A project is a collection of network-wide (physical or virtual) hosts processes that share a same tag defined as the project-id which is shared by a collection of internetwork-ed Solaris (physical or virtual) systems. Within each participating host those corresponding processes are further gathered on tasks by means of a common task-id. In the scope of a single host, a project has always one or more subordinate tasks.

The project-ids are gathered in a project database which can be local (/etc/project) or remote (NIS, LDAP or DNS). On this post I'll cover just the local case, but you can grasp an idea of how to implement it on NIS by reading other posts of mine.

For an appropriate project setup, it's useful to distinguish host's processes that derive from a login event from those that do not, because when a login is involved there's an additional way of defining the initial project to be associated with that login, and thus its main process and all its child/derived processes. In general, when processes are launched, the selected project will be deduced from the account which is used to launch the process according to the defined associations in the standard project database of the system.

By the way, a process is tied to a single project-id (project), but be aware that a user or a group can be assigned to multiple project-ids (projects). The processes that a user launches can be associated with any project that this user is associated to (either explicitly by user-name or implicitly by groups memberships) in the standard project database of the system. Of course, the super-user can assign any process to any project.

The raw view of the out-of-the-box project database is as follows:

$ cat /etc/project
system:0::::
user.root:1::::
noproject:2::::
default:3::::
group.staff:10::::


This database can also be listed more verbosely as:

$ projects -l
system
    projid : 0
    comment: ""
    users  : (none)
    groups : (none)
    attribs:
user.root
    projid : 1
    comment: ""
    users  : (none)
    groups : (none)
    attribs:
noproject
    projid : 2
    comment: ""
    users  : (none)
    groups : (none)
    attribs:
default
    projid : 3
    comment: ""
    users  : (none)
    groups : (none)
    attribs:
group.staff
    projid : 10
    comment: ""
    users  : (none)
    groups : (none)
    attribs:


As introduced, for logins events there's an extended user attribute "database" in /etc/user_attr which may or may not list the initial (but previously defined) project to be assigned to any user's processes since upon login. If no project is specified in /etc/user_attr then the search for the assignment will proceed to /etc/project looking for a match in the following order:

  1. user.user-name
  2. group.user-group
  3. The special project called default (if present)

If no suitable project is not found, then the login event or process launch is denied.

Now let's try a few examples in order to get better acquainted with projects. Let's define the marketing project for the john account in /etc/user_attr:

# usermod -K project=marketing john

And to verify it:

# getent user_attr john
john::::project=marketing


or

# userattr project john
marketing

To remove any project for the john account in /etc/user_attr:

# usermod -K project= john

Assuming the primary group of the john account as mkt01, the (fall-back) alternatives in /etc/project for not using /etc/user_attr could be:

# projadd user.john
# projects -l user.john
user.john
        projid : ...
        comment: ""
        users  : (none)
        groups : (none)
        attribs:

or

# projadd group.mkt01
# projects -l group.mkt01
group.mkt01
        projid : ...
        comment: ""
        users  : (none)
        groups : (none)
        attribs:


or none of the above, as long as the default project is present:

# projects -l default
default
        projid : 3
        comment: ""
        users  : (none)
        groups : (none)
        attribs:


Now, another very important application of the project database is for the workloads that do not derive from a login event, but rather are typically started as services or similar background processes, such as the Apache HTTP server. Such "special kind" of workloads, when well planned and administered typically take advantage of projects for both extended accounting and resource control.

As an example, let's set up a dedicated project to an Apache HTTP server that has been just installed and is running under the webservd account. Well, that's not quite exactly the case because, in reality, what traditionally happens is that a root process is launched and forks some child processes that are assigned to a different low-privileged webservd (or other) account that (hopefully) cannot log in to the system. At first, one might think that the following output is due to no project being assigned anywhere for the webservd account, but that's only partially true:

$ id -p webservd
uid=80(webservd) gid=80(webservd) projid=3(default)


$ ps -o user,pid,ppid,project -p "`pgrep -f httpd`"
    USER   PID  PPID  PROJECT
    root   559     1  system
webservd   577   559  system
webservd   591   559  system
webservd   593   559  system
webservd   604   559  system
webservd   607   559  system
webservd   616   559  system

  
These output are expected. The id command is deducing the project for new processes that would be launched in the event of a successful webservd log in to the system, which, of course, (and hopefully) will never happen. And it's truly expected that in a standard (out-of-the-box) setup the default project gets selected in the absence of any other explicit project assignments. But for the ps command listing the explanation is different. In this last case, all httpd child processes (577, 591, 593, 604, 607 and 616) derive from the same parent process (559) which was launched as root, thus inheriting the the system project that is associated to root. In Solaris, this launch actually happens from an SMF service (svc:/network/http:apache22) method which encapsulates the standard Apache HTTP server Control Interface (/usr/apache2/2.2/bin/apachectl; APACHECTL(8)) but unfortunately omits setting a project upon firing the service.

Fixes for problems such as the one above exemplified are certainly possible, but at first it's necessary to define a new project workload (www, for instance). As good practice, not that it's actually required (due to what was explained above), the webservd account should be assigned to this new project. One way to accomplish the task takes a single projadd -U command but for demonstration purposes I'll split it into a projadd followed by a projmod -a -U:

# projadd -c "World Wide Web" www
# projects -l www
www
        projid : 100
        comment: "World Wide Web"
        users  : (none)
        groups : (none)
        attribs:


# projmod -a -U webservd www
# projects -l www
www
        projid : 100
        comment: "World Wide Web"
        users  : webservd
        groups : (none)
        attribs:


By the way, if after creating a project it became necessary to alter some of its attributes and if there are processes already running under this project, it's possible to force them to update their project assignment by means of a projmod -A command. If one is uncertain and no processes are running yet under the project (as on the Apache HTTP server example above; no one is running assigned to the www project), just a harmless warning message is displayed:

# projmod -A www
projmod: Updating ... succeeded with following warning message.
WARNING: No process found ... The project is not updated.


Now focusing on the possible fixes to the issue of having background processes running under undesired projects such as the system project in the example above, there a two solutions that I know:

1) The simpler, but less than ideal "fix" is to "manually" move the processes to the desired project. The move does not required the inconvenience of restaring the processes (in this example, the Apache HTTP server processes). The disadvantage is that it does not integrate well in an automated management as it's not integrated into SMF. The "fix" consists on issuing the following command:

# pgrep -f httpd | xargs -t -l newtask -p www -c
newtask -p www -c 577
newtask -p www -c 616
newtask -p www -c 559
newtask -p www -c 591
newtask -p www -c 593
newtask -p www -c 607
newtask -p www -c 604


Et voilà!

# ps -o user,pid,ppid,project -p "`pgrep -f httpd`"
    USER   PID  PPID  PROJECT
    root   559     1  www
webservd   577   559  www
webservd   591   559  www
webservd   593   559  www
webservd   604   559  www
webservd   607   559  www
webservd   616   559  www


2) The more complicated "fix" is to deal with SMF. On this post I won't go too deep in how to properly or ideally accomplish the task. I'll just indicate the central change that has to be done letting clear that by not following the proper procedures to "patch" the SMF service, the "fix" could be lost when applying future updates or when performing system upgrades. I wish I'll have time to dedicate a post on how to properly do this, but for now I suggest doing just the following:

Identify the involved SMF method:

# svccfg -s apache22 listprop start/exec
start/exec astring     "/lib/svc/method/http-apache22 start"


# ll /lib/svc/method/http-apache22
-r-xr-xr-x   1 root  bin  ... /lib/svc/method/http-apache22


Edit the method and hard-code the /usr/bin/newtask command with the desired project (www) in the indicated line (138) as highlighted below:

# chmod 775 /lib/svc/method/http-apache22

# grep -n apachectl /lib/svc/method/http-apache22
138:... /usr/bin/newtask -p www ${APACHE_BIN}/apachectl ... 2>&1


# chmod 555 /lib/svc/method/http-apache22

The next time the service restarts everything shall be fine and under the new project. If, in addition, an immediate change is required but a standard restart would risk disturbing the services, just apply the solution (1) in addition.
 

Sunday, March 13, 2016

DNS client configuration

This is a quick web log on how to manually configure the DNS client.
I already have a few other posts on DNS but this topic was missing.
The closest I've logged was part of an AI Configuration Profile.

I assume that an active (on-line) DefaultFixed NCP is established.
The DNS server IP address is 192.168.10.1 and domain is business.corp.

If old or damaged configuration is present, the following command should probably remove any old or bad setting allowing a start over from scratch configuration such as on a fresh system with any DNS configuration:

# nscfg unconfig -v svc:/network/dns/client:default
unconfiguring DNS...
Delete customizations.
Refresh ... : .../svccfg -s .../dns/client:default refresh
successful unconfigure.


To manually configure the DNS client, perform the following:
(config/domain is unnecessary if don't run DNS on your LAN)
(for more DNS client SMF properties check resolv.conf(4))

# svccfg -s dns/client
...> listprop config/*
config/value_authorization astring     solaris.smf...

...> setprop config/nameserver = net_address: (192.168.10.1) 
...> setprop config/domain = astring: ("business.corp") 
...> listprop config/*
config/value_authorization astring     solaris.smf...
config/nameserver          net_address 192.168.10.1
config/domain              astring     business.corp

...> select default
.../dns/client:default> refresh
 
.../dns/client:default> quit

 
For legacy compatibility do:
 
# nscfg export -v svc:/network/dns/client:default
exporting DNS legacy...
Looking in /etc/mnttab, for lofs mount.
Save new legacy file...
    Legacy contents identical. skip save
successful export.
No change to FMRI: svc:/network/dns/client:default


And check...

# cat /etc/resolv.conf 
#
# _AUTOGENERATED_FROM_SMF_V1_
#
# WARNING: THIS FILE GENERATED FROM SMF DATA.
#   DO NOT EDIT THIS FILE.  EDITS WILL BE LOST.
# See resolv.conf(4) for details.

domain    business.corp
nameserver    192.168.10.1

    

And to finish, of course, (if not already so) we have to tell the system to consider the above DNS client configuration on host name resolutions (I have another post with additional details about name-services/switch):

# svccfg -s name-service/switch 
...> setprop config/host = astring: "files dns" 
...> select default 
.../name-service/switch:default> refresh 
.../name-service/switch:default> quit

Make sure the affected SMF services are running:

# svcs dns/client name-service/switch
STATE   STIME    FMRI
online  14:05:32 svc:/system/name-service/switch:default
online  14:41:07 svc:/network/dns/client:default

     
NOTE
Under Solaris 11 Express the dns/client SMF service just manages the associated daemon and doesn't hold any user configuration yet. The DNS client configuration is still done by editing the /etc/resolv.conf file directly, as usual.
  

Manual wired connection

This post is to log the most basic network setup to a Solaris 11 box.
Since Solaris 11/11 the network configuration procedure evolved.
While a lot of great things kicked in, it became more complex.
By Solaris 11.3 the procedures seems somewhat stable.

To make justice, the Solaris on-line documentation has been always great and under a continuous effort of improvement and correctness.

But when all that's required is a straightforward old and good static IP configuration to a standard wired ethernet network, the lots of new frameworks and subsystems may get in the way. The more you're in a hush, the more these small complexities can drive you mad. So, I tried to write this post as a sort of a more strait "complete" yet "minimalist" example.

As a minimum I assume:
  • An on-line DefaultFixed NCP.
  • A wired link that was already renamed to e0.
  • Basic DNS services just for Internet access.
  • Basic /etc/hosts for local host name resolution.
  • The host being configured is box-01 at 192.168.10.10
  • The gateway is at 192.168.10.1

CLEAN-UP

If you have some left over configuration from other scenarios or from failed attempts, you can try some of following commands in order to start over from the scratch and follow the rest of this post to the bottom:

# ipadm delete-addr e0/v4
...

# ipadm delete-ip e0
...

# route -p show
...

# route -p delete ...
...

# route flush
...
  
Visit the post DNS client configuration for its specific clean-up.

CONFIGURATION

Create the e0 ip interface over the link of the same name.
(I simply don't have any reason to use different names right now)

# ipadm create-ip e0
# ipadm show-if

IFNAME     CLASS    STATE    ACTIVE OVER
lo0        loopback ok       yes    --
e0         ip       down     no     --


Set up the static IP address to be used by the interface.
(An unambiguous /etc/hosts entry can be used instead of the IP)
(Depending on the IP, it may require a /prefixlen or /etc/netmasks)

# ipadm create-addr -T static -a 192.168.10.10 e0/v4
# ipadm show-addr

lo0/v4            static   ok           127.0.0.1/8
e0/v4             static   ok           192.168.10.10/24
lo0/v6            static   ok           ::1/128


Set up the persistent route to the default gateway to be used.
(Assume that the default gateway is at 192.168.10.1)

# route -p add default 192.168.10.1
add net default: gateway 192.168.10.1
add persistent net default: gateway 192.168.10.1


# route -p show
persistent: route add default 192.168.10.1


# grep default /etc/inet/static_routes-DefaultFixed
default 192.168.10.1


# netstat -rn -f inet 

Routing Table: IPv4
 Destination     Gateway     Flags Ref  Use   Interface

------------- -------------- ----- --- ------ ---------
default       192.168.10.1   UG      8   7774          
127.0.0.1     127.0.0.1      UH      2   2694 lo0      
192.168.10.0  192.168.10.10  U       3    196 e0
       

Next, configure the DNS client accordingly.

Finally, check if you have a reasonably basic /etc/hosts in place:
   
# cat /etc/hosts
#
# ...
#

::1             localhost
127.0.0.1       localhost              loghost
#
192.168.2.10    box-01.business.corp   box-01

  

Friday, August 1, 2014

DNS configuration file

By default, the DNS configuration file is /etc/named.conf.
The location of this file is good and bad at the same time.
It's good because it's on a standard UNIX location.
It's bad because it isn't on dedicated directory.
 
In order to improve administration it's necessary to dedicate a more stable directory and decouple, as much as possible, configuration detail that are subject to more frequent changes (DNS zone data) from those that don't, such as global options.
 
Consider all the assumptions presented in my DNS configuration.
There are two scenarios, one of them specific to a DNS internal root.
 
I) The DNS internal root main configuration file could be:
    (This is for internal root servers A, B, C and D)
 
#
#       Business Corp.
#
#       DNS internal root main configuration file.
#       Global options should be gathered on this file.
#       last update:  August 1, 2014.

#
 
options {
  version none;
  directory "/var/named";
  # ...
};
 
# Internal root.
zone "." in {
  type master;
  file "db.root";

  recursion no;
};

  
# Loopback zone.
zone "0.0.127.in-addr.arpa." in {
  type master;
  file "db.127.0.0";

  notify no;
};

    
# End of File.
      
II) The internal DNS server main configuration file could be:
    (This is for internal top-level servers NS00, NS01 and NS02

#
#       Business Corp.
#
#       DNS internal server main configuration file.
#       Global options should be gathered on this file.
#       last update:  August 1, 2014.

#
  
options {
  version none;
  directory "/var/named";
  # ...
};
 
# Internal root.
zone "." in {
  type hint;
  file "db.cache";

  recursion no;
};


# Loopback zone.
zone "0.0.127.in-addr.arpa." in {
  type master;
  file "db.127.0.0";

  notify no;
};

  
# Zones data (more frequently changed)
include "named.zones";
  
# End of File.

As soon as I'm satisfied with the global options the file won't change.
This is precisely my intention: administration limited to /var/named.
  
The file /var/named/named.zones will have other nested includes.
Most probably or ideally one additional nesting (include file) per zone.
   

DNS zone data source files

There is a tedious aspect of setting up DNS zone data.
It how it will or should be organized within the file system.
This particular post seeks to address this specific point.

I'll take the same approach used for NIS maps' source files.
Please, visit that other post for a longer description and consideration.
 
# zfs create rpool/VARSHARE/named

# zfs list -t all -r rpool/VARSHARE
NAME                  USED  AVAIL  REFER  MOUNTPOINT
rpool/VARSHARE         52K  11.8G    40K  /var/share
rpool/VARSHARE/named   31K  11.8G    31K  /var/share/named


# chmod -R 750 /var/share/named

# ln -s /var/shared/named /var/named
# ls -lh /var | grep ^l
...

lrwxrwxrwx   1 root     root ... dns -> /var/share/named
...

For further organization no additional ZFS file systems are needed.
A simple directory structure within /var/named will do.
  
Configure the directory option accordingly in /etc/named.conf:

options {
  # ...
  directory "/var/named";
  # ...
};
  

DNS zone data

Apart from installing and configuring DNS itself, a crucial preliminary step is to structure and prepare the DNS zone data source files. In what follows, I assume that all the structure and contents have been addressed as defined on the preceding posts (previous links).
  
Take the internal DNS servers NS00 thru NS02 (below DNS internal roots).
Their named.zones included by /etc/named.conf could be as follows:
  
zone "business.corp" {
  type master;
  file "master/db.business.corp";
};
 
zone "10.in-addr.arpa" {
  type master;
  file "master/db.10";
};
 
zone "168.192.in-addr.arpa" {
  type master;
  file "master/db.192.168";
};
   
NOTE
Of course, it's not recommended to have a multi-master setup.
This means, just as example, that only NS00 should be master.
Hence, it suffices to substitute master for slave for NS01 and NS02.
The contents of each of the above zone data file in master is as follows:

I) business.corp

;
;       Business Corp.
;
;       Internal DNS (top-level) server forward zone.
;       last update:  August 5, 2014.

;

 
$TTL 3h 

@  IN  SOA  NS00.business.corp.  hostmaster.business.corp.  ( 
            1    ; Serial 
            3h   ; Refresh after 3 hours 
            1h   ; Retry after 1 hour 
            1w   ; Expire after 1 week 
            1h ) ; Negative caching TTL of 1 hour

; Authoritative name servers.


                    IN  NS  NS00.business.corp. 
                    IN  NS  NS01.business.corp.
                    IN  NS  NS02.business.corp.

; The internal root servers A records.

A                   IN  A  10.0.0.10
B                   IN  A  10.0.0.20
C                   IN  A  10.0.0.30
D                   IN  A  10.0.0.40


; The internal top-level servers A records.

NS00                IN  A  10.0.1.10
NS01                IN  A  10.0.1.20

NS02                IN  A  10.0.1.30

; Other internal hosts A records.

; ...
 
; End of File.

II) 10.in-addr.arpa

;
;       Business Corp.
;
;       Internal DNS (top-level) server reverse zone.
;       last update:  August 5, 2014.

;

 
$TTL 3h 

@  IN  SOA  NS00.business.corp.  hostmaster.business.corp.  ( 
            1    ; Serial 
            3h   ; Refresh after 3 hours 
            1h   ; Retry after 1 hour 
            1w   ; Expire after 1 week 
            1h ) ; Negative caching TTL of 1 hour

; Authoritative name servers.


                    IN  NS  NS00.business.corp. 
                    IN  NS  NS01.business.corp.
                    IN  NS  NS02.business.corp.

; The internal root servers PTR records.

10.0.0              IN  PTR A.business.corp.
20.0.0              IN 
PTR B.business.corp.
30.0.0              IN  PTR C.business.corp.
40.0.0              IN  PTR D.business.corp.

; The internal top-level servers PTR records.

10.1.0              IN  PTR NS00.business.corp.
20.1.0              IN  PTR NS01.business.corp.
30.1.0              IN  PTR NS02.business.corp.

; Other internal hosts PTR records.

; ...
 
; End of File.

III) 168.192.in-addr.arpa

;
;       Business Corp.
;
;       Internal DNS (top-level) server reverse zone.
;       last update:  August 5, 2014.

;

 
$TTL 3h 

@  IN  SOA  NS00.business.corp.  hostmaster.business.corp.  ( 
            1    ; Serial 
            3h   ; Refresh after 3 hours 
            1h   ; Retry after 1 hour 
            1w   ; Expire after 1 week 
            1h ) ; Negative caching TTL of 1 hour

; Authoritative name servers.


                    IN  NS  NS00.business.corp. 
                    IN  NS  NS01.business.corp.
                    IN  NS  NS02.business.corp.

; Other internal hosts PTR records.

; ...

; End of File.

  

Thursday, July 31, 2014

DNS loopback zone

The loopback zone is part of a DNS configuration.
Its purpose is to handle the 127.0.0.0/24 network.
By convention and good practice each DNS server must handle it.
Naturally, the above recommendation doesn't apply to DNS root servers. 
In general the localhost number is 127.0.0.1.
Hence, the zone file is called db.127.0.0.

Consider the example given on the post DNS internal root.
The top-level (below DNS internal roots) internal DNS servers are:
  • NS00.business.corp
  • NS01.business.corp 
  • NS02.business.corp 
  
Each of them would have the following loopback zone configuration:
(the following are the contents of db.127.0.0)

;  
;       Business Corp.  
;  
;       The loopback zone.
;       last update:    July 31, 2014.
 
;

$TTL 3h

@  IN  SOA  NS00.business.corp.  hostmaster.business.corp.  (
            1    ; Serial
            3h   ; Refresh after 3 hours
            1h   ; Retry after 1 hour
            1w   ; Expire after 1 week
            1h ) ; Negative caching TTL of 1 hour


; Authoritative name servers.
 
   IN  NS  NS00.business.corp.
   IN  NS  NS01.business.corp.

   IN  NS  NS02.business.corp.

; The localhost PTR record.
 
1  IN PTR localhost.

; End of File.
 
In this particular case /etc/named.conf must contain:

zone "0.0.127.in-addr.arpa." in {
  type master;
  file "db.127.0.0";

  notify no;
};

   

Internal DNS server

Internal DNS servers are those behind a firewall which provide host name resolution only within an organization's internal internetwork (or Intranet) and don't directly connect to the Internet. They differ from DNS internal root servers (that define their own root zone) and external DNS servers (that use a standard DNS root hints and directly connect to the Internet for external name resolutions).

The key distinctive configuration is regarding the contents of the (conventionally) so called db.cache containing a custom root hints with pointers to the organization's DNS internal root servers instead of a standard DNS root hints used for ordinary Internet-wide resolution.

Considering the examples given on the DNS internal root post as a base, the top-level internal servers (right below DNS internal root servers) are:
 
  • NS00.business.corp
  • NS01.business.corp 
  • NS02.business.corp 

Each of them would have the following custom root hints configuration:
(the following is a partial excerpt of their db.cache)

;
;       Business Corp.
;
;       DNS internal root servers.
;       last update:    July 31, 2014.

;

.                     3600000  IN  NS    A.business.corp.
                      3600000  IN  NS    B.business.corp. 
                      3600000  IN  NS    C.business.corp. 
                      3600000  IN  NS    D.business.corp.
 
A.business.corp.      3600000  IN  A     10.0.0.10
B.business.corp.      3600000  IN  A     10.0.0.20
C.business.corp.      3600000  IN  A     10.0.0.30
D.business.corp.      3600000  IN  A     10.0.0.40  

; End of File. 

In this particular case, their (NS00 thru NS02) main configuration file, /etc/named.conf would contain:

zone "." in {
  type hint;
  file "db.cache";

  recursion no;
};