Category: Technology

Controlling Printer Outlet

We normally keep our printer turned off. Residential printer standby can have a decent draw. It’s something you have to research specific to your printer — some have low single-digit standby draw and waste ink when powered on and off. Others, like ours, has a non-trivial standby draw that isn’t offset by ink savings. The problem is that you’ve got to turn the printer on, print your stuff, and then remember to turn it off. The tiny person remote power controller (i.e. Anya) works for this, but it’s not an elegant automated solution.

Scott set up a smart outlet for the printer – you can tell the Echo to turn the printer outlet on and off now. But you still have to remember to turn it off 🙂

So I set up a print queue on the server & all print jobs are submitted to the server-based queue. A scheduled task on the server checks the print queue for jobs and turns the printer on when jobs are found. When the printer is on but no jobs are in the queue, it waits ten minutes and checks again (otherwise you could turn the printer on & have the batch immediately turn it off. Or worse the job could be out of the queue but still printing!), then turns the printer off if there are still no jobs in the queue. Voila, now the printer turns itself on when you want to print something and it remembers to turn itself off later.

The tricky bit was figuring out how to post ‘ON’ and ‘OFF’ to the OpenHAB2 REST API. -Body with just the command:

Invoke-WebRequest -URI ‘http://openhabserver.domain.gTLD:8080/rest/items/Outlet1’ -ContentType “text/plain” -Method POST -Body ‘OFF’

The script is available at https://github.com/ljr55555/miscPowershell/blob/master/printQueueMonitor.ps1

OUD Returning Some DirectoryString Syntax Values As UTF-8 Encoded Bytes

We are still in the process of moving the last few applications from DSEE to OUD 11g so the DSEE 6.3 directory can be decommissioned. Just two to go! But the application, when pointed to the OUD servers, gets “Unable to cast object of type ‘System.Byte[]’ to type ‘System.String'” when retrieving values for a few of our DirectoryString syntax custom schema.

This code snippet works fine with DSEE 6.3.

string strUserGivenName = (String)searchResult.Properties["givenName"][0]; 
string strUserSurame = (String)searchResult.Properties["sn"][0]; 
string strSupervisorFirstName = (String)searchResult.Properties["positionmanagernamefirst"][0]; 
string strSupervisorLastName = (String)searchResult.Properties["positionmanagernamelast"][0];

Direct the connection to the OUD 11g servers, and an error is returned.

     

The attributes use the same syntax – DirectoryString, OID 1.3.6.1.4.1.1466.115.121.1.15.

00-core.ldif:attributeTypes: ( 2.5.4.41 NAME ‘name’ EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} X-ORIGIN ‘RFC 4519’ ) 
00-core.ldif:attributeTypes: ( 2.5.4.4 NAME ( ‘sn’ ‘surname’ ) SUP name X-ORIGIN ‘RFC 4519’ ) 
00-core.ldif:attributeTypes: ( 2.5.4.42 NAME ‘givenName’ SUP name X-ORIGIN ‘RFC 4519’ ) 

99-user.ldif:attributeTypes: ( positionManagerNameMI-oid NAME ‘positionmanagernamemi’ DESC ‘User Defined Attribute’ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN ‘user defined’ ) 
99-user.ldif:attributeTypes: ( positionManagerNameFirst-oid NAME ‘positionmanagernamefirst’ DESC ‘User Defined Attribute’ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN ‘user defined’ ) 
99-user.ldif:attributeTypes: ( positionManagerNameLast-oid NAME ‘positionmanagernamelast’ DESC ‘User Defined Attribute’ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN ‘user defined’ ) 

I’ve put together a quick check to see if the returned value is an array, and if it is then get a string from the decoded byte array.

string strUserGivenName = (String)searchResult.Properties["givenName"][0]; 
string strUserSurame = (String)searchResult.Properties["sn"][0]; 

string strSupervisorFirstName = "";
string strSupervisorLastName = "";
if (searchResult.Properties["positionmanagernamefirst"][0].GetType().IsArray){
    strSupervisorFirstName = System.Text.Encoding.UTF8.GetString((byte[])searchResult.Properties["positionmanagernamefirst"][0]);
}
else{
    strSupervisorFirstName = searchResult.Properties["positionmanagernamefirst"][0].ToString();
}

if (searchResult.Properties["positionmanagernamelast"][0].GetType().IsArray){
    strSupervisorLastName = System.Text.Encoding.UTF8.GetString((byte[])searchResult.Properties["positionmanagernamelast"][0]);
}
else{
    strSupervisorLastName = searchResult.Properties["positionmanagernamelast"][0].ToString();
}

Voila

The outstanding question is if we need to wrap *all* DirectoryString syntax attributes in this check to be safe or if there’s a reason core schema attributes like givenName and sn are being returned as strings whilst our add-on schema attributes have been encoded.

Isolated Guest Network On Merlin 380.69_2 (Asus RT-AC68R)

We finally got rid of Time Warner Cable / Spectrum / whatever they want to call themselves this week’s overpriced Internet that includes five free outages between 1100 and 1500 each day. But the firmware on the new ISP’s router doesn’t have a facility to back up the config. And if we’re going to have static IPs for all of our speakers, printers, servers … we don’t want to have to re-enter all of that data if the router config gets reset. Same with configuring the WiFi networks. And, and and. So instead of using the snazzy new router, we are using our old router on .2, the new router on .1 … and everything actually connects to the old router, uses the DHCP server on the old router. And only uses the new router as its default gateway. Worked fine until we tried to turn on the guest network.

I found someone in Internet-land who has the exact same configuration and wants to permit guests to use the LAN printer. His post included some ebtables rules to allow guest network clients access to his printer IP. Swapped his printer IP for our router IP and … nada.

And then I realized that the router is not the packet destination IP when the guest client attempts to communicate outside our network. The router is the destination MAC address. So you cannot add an ebtables rule to the router’s IP address and expect traffic to flow.

The first thing you need to do is figure out the upstream router’s MAC address. From the Asus, you can query the arp table. If the command says “No match found in # entries”, ping the router and try again.

root@ASUS-RT-AC68R:/tmp/home/root# arp -a 10.5.5.1
? (10.5.5.1) at a3:5e:c4:17:a3:c0 [ether] on br0

The six pairs of hex numbers separated by colons – that’s the MAC address. You have to allow bidirectional communication from the guest network interface (wl0.2 for us) with the upstream router’s MAC address. You also have to allow broadcast traffic so guest devices are able to ARP for the router’s MAC address.

To have a persistent config, enable jffs and add the config lines to something like services-start:

root@ASUS-RT-AC68R:/tmp/home/root# cat /jffs/scripts/services-start
#!/bin/sh
logger "SERVICES-START: script start"
# Prevent Echo dots from sending multicast traffic to speaker network
ebtables -I FORWARD -o wl0.1 --protocol IPv4 --ip-source 10.0.0.36 --ip-destination 239.255.255.250 -j DROP
# Guest network - allow broadcast traffic so devices can ARP for router MAC
ebtables -I FORWARD -d Broadcast -j ACCEPT
# Guest network - allow communication to and from router MAC
ebtables -I FORWARD -s a3:5e:c4:17:a3:c0 -j ACCEPT
ebtables -I FORWARD -d a3:5e:c4:17:a3:c0 -j ACCEPT
# This should be automatically added for guest network, but it goes missing sometimes so I am adding it again
ebtables -A FORWARD -o wl0.2 -j DROP
ebtables -A FORWARD -i wl0.2 -j DROP

 

Use -L to view your ebtables rules:

root@ASUS-RT-AC68R:/tmp/home/root# ebtables -L
Bridge table: filter

Bridge chain: INPUT, entries: 0, policy: ACCEPT

Bridge chain: FORWARD, entries: 16, policy: ACCEPT
-d a3:5e:c4:17:a3:c0 -j ACCEPT
-s a3:5e:c4:17:a3:c0 -j ACCEPT
-d Broadcast -j ACCEPT
-p IPv4 -o wl0.1 --ip-src 10.0.0.36 --ip-dst 239.255.255.250 -j DROP
-o wl0.2 -j DROP
-i wl0.2 -j DROP

Voila, guests who can access the Internet & DNS on the .1 router, but cannot access anything on the internal network. Of course you can add some specific IPs as allowed destinations too – like the printers in the example that started me down this path.

DSEE 6.3 To OUD 11g Transition

There’s no direct path to replicate data from DSEE6.3 to OUD11g. Not unreasonable since DSEE is the Sun product based on the Netscape Directory Server and OUD is the Oracle product based on OpenLDAP – they weren’t exactly designed to allow easy coexistence that would permit customers to switch from one to the other. Problem is, with Oracle’s acquisition of Sun & axing the DSEE product line … customers *need* to interoperate or do a flash cut.
Since our Identity Management (IDM) platform was not able to prep development work and implement their changes along with the directory replacement, a flash cut was right out. I’ve done flash cuts before — essentially ran two completely different directories in parallel with data fed from the Identity Management platform, tested against the new directory using quick modification to the OS hosts file, then reconfiguring the virtual IP on the load balancer to direct the existing VIP to the new service hosts. Quick/easy fail-back is to set the VIP to the old config and sort out whatever is wrong on the new hosts. A lot lower risk than a traditional ‘flash cut’ approach as long as you trust the IDM system to keep data in sync. But lacking an IDM system, flash cut is typically a non-starter anyway.
There is a migration path. Oracle put some development effort into the DSEE product line prior to discontinuing it. DSEE7 was the Sun distributed “next version”. It was not widely deployed prior to the Oracle acquisition. Oracle took over DSEE7 development but called it DSEE11 (to match the OUD version numbering, I guess?). Regardless of the rational, you’ll see the “next version” DSEE product referred to as both DSEE7 and DSEE11.
There’s not a direct replication between Oracle DSEE11 and Oracle OUD11. Oracle created a “replication gateway” that handles, among other things, schema name mapping (only Netscape would use attribute names like nsAccountLockout, and that nomenclature carried through to the Sun product). Oracle did a decent job of testing DSEE11<=>OUD11 Replication Gateway interoperability. I don’t know if they just assumed DSEE6 would work because DSEE11 did or if they assumed the installation base for DSEE6 was negligible (i.e. didn’t bother to test older revisions) but we found massive bugs in the replication gateway working with DSEE6. “You cannot import the data to initialize the OUD11 directory” type of bugs which I was willing to work around by manually editing the export file, but subsequent “updates do not get from point ‘A’ to point ‘B’ bugs too. The answer from Oracle was essentially “upgrade to DSEE11” … which, if i could flash-cut upgrade DSEE6 to DSEE11 (see: IDM platform couldn’t do that), I could just cut it to OUD11 and be done. Any non-trivial change was a non-starter, but Oracle wasn’t going to dump a bunch of development time into fixing replication for a dead product to their shiny new thing.
I worked out a path that used tested and working components — DSEE6 replicated just fine with DSEE11. DSEE11 replicated just fine with the OUD11g replication gateway, and the OUD11g replication gateway replicated fine with OUD11g. Instead of introducing additional expense and time setting up dedicated replication translation servers, I installed multiple components on the new servers. There is a DSEE11 directory on one of the new OUD servers, the replication gateway on another one of the new OUD servers, and (of course) the OUD11g directory that we actually intended to run on the new servers is on those new OUD servers.
This creates additional monitoring overhead – watching replication between three different directories and ensuring all of the services are running – but allows the IDM platform to continue writing changes to the DSEE6.3 directory until they are able to develop and test changes that allow them to use OUD11g directly.

Systemd (a.k.a. where did my log files go!?!?!)

A systemd Primer For sysvinit Users

Background:

Starting in Fedora 15 and RHEL 7, systemd replaces sysvinit. This is a touchy subject among Unix folks – some people think it’s a great change, others think Linux has been ruined forever. Our personal opinions of the shift doesn’t matter: vendors are implementing it, WIN Linux servers use it, so we need to know it. Basically, throw “systemd violates the minimalist, modular philosophy at the core of Unix development” on the “but emacs is so awesome, why are we using vim” and “BETA outperforms VHS any day of the week” pile.

Quick terminology – services are now called units. You’ll see that word a lot. A unit is configured in a “unit file”. Additionally, “run levels” (0-6) have been replaced with the concept of “targets” that have friendly names.

What’s the difference?

Sysvinit wasn’t designed to know about your system, it was designed to run scripts on your system. Sysvinit essentially runs scripts, whereas systemd is a service manager. Systemd knows about the system. One place this becomes apparent – if you manually run the run line from a sysvinit script then check the service status, it will show running because the binary has a PID. If you do the same with systemd, it will say the service is down. This is like Windows – if you have a Docker service that runs “”C:\Program Files\Docker\Docker\com.docker.service”” set to run manually, and use start-run to run the exact same string … the service will not show as running.

Systemd manages a lot of different unit types. As application owners, we’ll use ‘service’ units. ‘Mount’ or ‘automount’ type units manage mountpoints. Socket and device unit types manage sockets (which have associated service unit files using the socket) and devices. Because systemd manages sockets, inetd/xinetd have been obsoleted.

Sysvinit scripts could run user-defined commands. If the init script for myapplication has a section called “bob”, you can run “service myapplication bob” and it will do whatever the ‘bob’ part of the script says to do. Systemd has a fixed list of directives – start, stop, restart, reload, status, enable, disable, is-enabled, list-unit-files, list-dependencies, daemon-reload. You cannot just make a new one.

Systemd may also require a system reboot for more than just kernel patches. This is really different, and I expect there will be a learning curve as to what requires a reboot.

Log files have “vanished”. If you are using a default installation, you won’t find /var/log/messages. You can use “journalctl -f” to tail the equivalent of the messages file. The systemd log files are stored in binary format – potentially corruptible, which is another aspect of the change Unix-types don’t care for.

What does systemd give me?

Systemd doesn’t just start/stop a service when run levels change. A unit can be started because it is configured to start on the runlevel (just like sysvinit scripts), if another service requires it, if the service abends, or if dbus triggers it. “If another service requires it” – that’s a dependency chain. Instead of defining an order and hoping everything you need was loaded by the time the init script ran, systemd allows you to include an “After” directive – units started before the current unit or “Before” – units that will not be started until the current unit starts. Additional directives for “Requires” – units which must be activated to activate the current unit and “Wants” – units that will be started in parallel with the current unit but failing to start these units will not fail the current unit.

A directive, “Conflicts”, allows systemd to identify other units that cannot coexist with the current unit. Conflicting units will be stopped to allow the current unit to start. In addition to the base command starting in the unit file (ExecStart), there are pre (ExecStartPre) and post (ExecStartPost) operations that are run before/after the base command. These could be related to the service itself but do not have to be. You could run a mail command line to alert an admin every time the unit starts or stops cleanly.

Another nice feature of systemd is user-level services – using systemctl –user will control unit files located in user-specific directories like /usr/lib/systemd/user/ and ~/.config/system/user/

Using systemd: (Warning: this is going to get odd)

You use systemctl to control units, and you use journalctl to view the binary blobs that have replaced log files. Use the man pages or your favourite search engine if you want details. The general syntax for systemclt is “systemctl operation unit.type” – e.g. “systemctl restart sendmail” would restart sendmail.

Chkconfig has been completely supplanted. Use “systemctl enable unit.type” and “systemctl disable unit.type” to control if a service auto-starts. Instead of using chkconfig –list, you can query the startup state of an individual unit. Use systemctl –is-enabled unit.type

There’s a service shell script that replaces ‘service’ that you used with sysvinit systems. It turns the old “service something-or-other action” into “systemctl action name.service” so it still works.

Here’s the odd part – it is quite easy to define a permitted sudo operation that allows a non-root user to control sysvinit services. Allow “service sendmail” and the user can run “service sendmail start”, “service sendmail stop”, “service sendmail status”, “service sendmail RandomStuffITossedIntoTheFile”. Because the service name and directive are swapped around in systemctl, we would have to enumerate each individual directive that should be permitted. More secure, because RandomStuffITossedIntoTheFile should not make the cut. But we haven’t done this yet. So until we go through and enumerate the reasonable actions (Are there directives beyond start/stop/status that we should be running? Do we have any business enabling and disabling our services?), submit the access request, confirm it’s all functioning as expected, and remove the “sudo service” access … continue using “sudo service something-or-other action”. We will advise you when the systemctl sudo access has been granted so we can start using the “new way” to control services on RHEL7 systems.

Unlike init scripts, changes to systemd unit files are not immediately activated on the system. Running “systemctl daemon-reload” makes systemd aware of the config change.

Using journalctl:

Our Unix team has implemented rsyslogd to output log data to the expected files. This means you can more or less ignore journalctl – tail/grep the log file as usual. I don’t foresee this changing in the near to mid term, but if you use cloud-hosted sandbox servers (i.e. boxes that don’t have the Unix group’s standard config) … journalctl is what happened to all the log files you cannot find.

To view logs specific to an individual unit, use journalctl -u unit.type. Additionally “systemctl unit.type status” will display the last handful of log lines from the unit.

Load Balance and Failover Sendmail Mailertable Relays

A coworker asked me today how to get the mailertable relays to load balance instead of fail over. Trick is to think beyond sendmail. The square brackets around hosts tell sendmail not to check for an MX record (you’re generally using an A record, so this saves a tiny little bit of time … not to mention *if* there is an MX record there, it creates a whole heap-o confusion). *But* the MX lookup is right useful when setting up load balanced or failover relay targets.

Single host relay in the mailertable looks like this:
yourdomain.gTLD      relay:[somehost.mydomain.gTLD]

If you want to fail over between relays (that is try #1, if it is unavailable try #2, and so on), you can stay within the mailertable and use:
yourdomain.gTLD      relay:[somehost.mydomain.gTLD]:[someotherhost.mydomain.gTLD]

Or even try direct delivery and fail back to a smart host:
yourdomain.gTLD      relay:%1:smart-host

But none of this evenly distributes traffic across multiple servers. The trick to load balancing within the mailertable is to create equal weight MX records in your domain to be used as the relay.

In ISC Bind, this looks like:
yourdomainmailrouting.mydomain.gTLD     IN MX 10 somehost.mydomain.gTLD.
yourdomainmailrouting.mydomain.gTLD     IN MX 10 somehost.mydomain.gTLD.

Once you have created the DNS records, simply use the MX record hostname in your mailertable:

yourdomain.gTLD      relay:yourdomainmailrouting.mydomain.gTLD

By leaving out the square brackets, sendmail will resolve an MX record for ‘yourdomainmailrouting.mydomian.gTLD’, find the equal weight MX records, and do the normal sendmail thing to use both.

Data Privacy

Facebook is getting a lot of attention for the information it gathers and how well it secures personal data you provide. We should look just as intently at other companies. Some provide services to individuals in exchange for advertising data, and some provide advertising targeting services without offering anything to the individuals being tracked.

LinkedIn — Maybe because “professional” information about oneself does not feel as private as that which is shared on Facebook, LinkedIn gets overlooked a bit. The companies I’ve worked for and titles I’ve held almost seem like public records. You can download a copy of “your data” (like Facebook, this is not apt to contain meta-data they’ve gathered regarding you – just data you have submitted to the site). In your settings, use the privacy tab and scroll down to “How LinkedIn uses your data” – the first selection is to download your data.

Nothing stunning – a list of contacts, my various employers and titles. But LinkedIn is trying to slurp in my entire contact list, maintain a web of people who know people, and allow advertisers to target users. There’s a whole tab apart from your privacy settings to control how your data is used for advertising purposes. “Advertisers” seem to be corporate hiring agents and recruiters, so this marketing is not always mentally classified as “advertising”.

LinkedIn also has a setting which allows you to opt-out (mine was on, and I’ve never opted in so I assume it is an opt-out deal) of having some of your data made available to third parties for policy and academic research.

And remember that Facebook Pixel? LinkedIn wants to track information about “websites you’ve visited” and “information you’ve shared with businesses” to show you more relevant jobs and ads.

Beyond the data feeling less private, having high-paying jobs that need my exact skill set and tend to hire people with my browsing history … well, that feels like a score compared to Facebook’s ad trying to coerce me once again to buy a pair of roller skates I already decided wouldn’t work for my daughter. Even if you’re not actively interested in changing jobs, it is nice to feel wanted. But that’s a nice veneer to data hording, analysis, and target marketing. They’ve even got a peculiar setting under the “Communications” tab that wants to use algorithms to analyze your messages to formulate suggested replies. This too seems to be an opt-out setting.

Google — no one uses Google+ (pity, that) but Google amasses information from searches, e-mails, Hangouts, Android phones. You can request an archive of your data through https://takeout.google.com — it takes a long time for the archive to be built, and it was an incredible amount of data. A few +1s from mis-clicks that there is no immediately obvious way to delete. “Bookmarks” that all appear to be map locations. A calendar that apparently was syncing with my home server back in 2009 since that’s the create date on all of the items. A whole folder for Chrome with 75 meg of browsing history and another meg of bookmarks (a meg of text is a *lot* of data, but I *love* that my bookmarks sync between devices). A handful of contacts that I assume my husband created in our shared account. The totality of every conversation I’ve ever had in Hangouts. Some Google Keep notes that I also assume are my husband’s from our shared account. My entire GMail mailbox, which is an obvious data source. The very tiny set of profile data I actually shared with Google.

Hell, Google has years worth of location data that I guess comes from my phone (it’s got fairly accurate lat/long coordinates, so GPS is the likely source). Following Google’s directions to delete the data didn’t work either (on the map, hit the hamburger menu then scroll ALL THE WAY DOWN to the ‘history’ selection”. Google both claims to have no history data for me and has 423 places on my timeline. Sooo, yeah, that would be history data. I finally managed to delete the stuff through my phone. There is a “Google Settings” app. Select “Location” from it, then “Google Location History”. There is a “Manage Activities” selection (use Google Maps to open it). Confirm you don’t want to use location history because, of course, it asks you to turn it on. Then use the hamburger menu button and select “Settings”. Waaay down at the bottom, there’s an option to delete all history or a date range of history. A couple of warnings later, the timeline map shows no data.

Then there are the photos. Gig after gig of photos. I had an Android phone that went into a reboot loop. I spent a few days wiping and reloading my phone, then failed back to an old phone. One of those iterations, evidently, slurped up all of the photos on my SD card because companies *want* your data. So the initial phone setup pushes you to backup your data, sync up your media, and generally upload ‘stuff’. One erroneous click and they’ve got metadata they’ll be able to keep forever. And there’s no readily apparent way to delete everything at once either. I’ve spent days on the web site deleting a couple hundred photos at a time. Not fun. Click the first picture, scroll down a bit, hold shift and click another picture. If you’re lucky, you didn’t select more than whatever the limit is (guessing 500) and you’ll get “389 Selected” in the upper left hand corner. At which point, you can click the delete and remove that chunk of photos. If you are not lucky, you get “2 Selected” and have to try again.

Ceasing data collection is much easier than removing data they’ve already grabbed. From your account settings, elect to “Manage your Google activity”. Then go into “Go To Activity Controls” and turn off (well, pause) whatever you want to turn off.

And I assume any bucket into which they’ve placed you based on previously gathered information will be retained even if you’ve deleted the underlying data.

 

Sendmail In CHROOT Jail

Running our sendmail mail relay in a chroot jail, ‘make’ does not update sendmail config files with changes. While I’m certain there’s a way to sort that, it’s a lot easier to go back to the old-school way of updating sendmail.cf and sendmail’s hash files.

Modifying Sendmail Configuration (sendmail.mc) on Servers with CHROOT Jailed Sendmail

  1. SSH to server using your ID
  2. Change to the sendmail service account (e.g. sudo /bin/su – sendmail)
  3. Change directory to the jailed sendmail /etc/mail locatio (e.g. cd /smt00p20/sendmail/etc/mail)
  4. vi sendmail.mc
  5. Make requisite changes and save file
  6. m4 sendmail.mc > sendmail.cf
  7. Under your ID, restart sendmail using “sudo systemctl stop sendmail stop;sudo systemctl start sendmail”
  8. Validate changes

Modifying Sendmail Data Files on Servers with CHROOT Jailed Sendmail

  1. SSH to server using your ID
  2. Change to the sendmail service account (e.g. sudo /bin/su – sendmail)
  3. Change directory to the jailed sendmail /etc/mail locatio (e.g. cd /smt00p20/sendmail/etc/mail)
  4. vi filetoedit
  5. Make requisite changes and save file
  6. makemap hash ./filetoedit.db < ./filetoedit
  7. Under your ID, restart sendmail using  “sudo systemctl stop sendmail stop;sudo systemctl start sendmail”
  8. Validate changes

Where filetoedit is the name of the data file. For example, run “makemap hash ./access.db < ./access” to update the changes to the access file into access.db

Corporate Privacy

We had the Senate & House Facebook thing playing Tue/Wed – kind of background noise because anyone who didn’t realize a billion dollar corporation offering a “free” service was making money somehow on the back-end … well, didn’t bother thinking about it. But there were a few interesting tidbits (not the least of which being how many things one can claim, before a Congressional panel, to be ignorant of in spite of the topic being germane to the core operation of one’s company). The thing that stood out most to me through two days of testimony is that no one questioned the validity of the underlying service – consumerism is good, hence serving ads more likely to convince a person to buy the product is good too. I’ve got friends exclaiming that they’ve found products they’d never have known existed without targeted ads — which to me sounds like you’ve spent money on “stuff” that you didn’t need enough to go out and research something to fill that gap. Not a bad thing per se, but certainly not the laudable endeavor they make personalized advertising out to be. The flip side to presenting me ads that are more likely to convince me to buy something (assuming this is true, which dunno … sounds good on the face of it, but I tend to be put off by it and less likely to buy something) is, well, me buying more ‘stuff’ which is not always to my economic benefit.

But when they got onto the topic of Facebook Pixels (which work around people who block third party cookies), it got me thinking about the lack of control we all have over metadata. A lot of companies serve a menagerie the third party cookies from their site, and then execute a couple of third party JS trackers too. Because, as a company, it provides those third parties with data that potentially help drive sales. In theory. But do those marketing companies have some kind of non-compete clauses included in the contract they write with WIN? Can FB, Adobe, Google, etc have code embedded in a telco’s site, take the info they gather from my telco’s embedded JS code, and use it to promote non-telecom services? Cable TV even though it competes with a component of our business? An alternate telecom even though it’s a major line of our business? Is there a meta-category of “people who looked at my site but also looked at two competitors sites” v/s “people who have only looked at my site”?  At least that’s governed by contract and might be tightly controlled — although I doubt an org like Facebook tracks the provenance of each bit of metadata it collects to isolate its usage, that’s based on a feeling rather than any knowledge of their internal algorithms.

Employees visiting various sites — what data to we leak and how can that be used? It’s not like my company has any sort of agreement in place to control how CompanyX uses data gathered as our employees use CompanyY’s web site. My super paranoid brain goes to the potential for abuse — a competitor using our information against us. Not the marketing company directly – like FB doesn’t sell my name and data (that’s what they make their money on after all, using my data to throw me into advertising buckets) … but the company gathering the data can get acquired. Quite a few companies use Triblio – some niche B2B tracking thing as well as Google Analytics. Now Google isn’t a big acquisition target, but some small B2B marketing company? VZ bought Yahoo, so it’s not like the only thing they’re buying is towers and fiber. VZ buys Triblio and we’re in the beginning stages of forming some new product line through some company that uses Triblio. VZ doesn’t exactly know what we’re planning to sell in six months … but they’ve got a good idea. Or even industrial espionage — it’s getting to the point it makes a lot more sense to target one of these data brokers than to target a specific company.

I get that’s a little far-fetched and more than a little paranoid. Is targeted marketing effective for companies too – are company-targeted ads convincing the company’s employees to buy more stuff on the company’s behalf?

As a company are we benefiting, harmed, or indifferent to information being gathered from our employees as they navigate the web. Employees are going to show up from an assigned netblock most of the time (i.e. from the office or VPN), so it isn’t like it’s a super-hard-to-ascertain where the individual works. Is there benefit to blocking the tracking ‘stuff’ on a corporate level (and maintaining a default browser config that blocks third party cookies)? Is there harm in blocking the trackers? The parade of horrors approach would say with Facebook/Google specifically, widespread blocking would necessitate some other revenue stream for the company (i.e. we’d end up buying 1$ hundred search passes or something). Dedicated targeted advertising companies – beyond putting a company out of business (e.g. Triblio which seems to be a dedicated marketing data company) or reducing revenue (e.g. Adobe since they’ve got other profitable lines of business), not much direct impact. A vividly imagined parade would be worldwide recession as psychologically engineered spending prompts disappear and consequently consumer spending retracts. Worst thing I can come up with is being perceived as a bunch of hypocrites who track everything customers do on their site but specifically took efforts to prevent employees from being tracked around the web.

House Facebook Hearings

Day two didn’t change my opinion from day one, but it does introduce a few new nuances. If you consider “my” information to be content (text, video, images, likes) that I’ve personally submitted to Facebook … sure I have some control over ‘my’ data. Not the granular level of control I would prefer, not always readily usable control, and like all things on the Internet (including user data downloaded by a third party), I don’t have control over what people who have access to my data can subsequently do with it. But Facebook has a whole other realm of my data — metadata from images or videos, geo-location information (maybe IP-based with low accuracy, maybe GPS with high accuracy), how long I spent looking at what content, what time of day I log on … and that’s just information gathered directly from my usage of the web site.

Block third party cookies in your web browser (seriously, do it) and see how often adobetm.com, disqus.com, doubleclick.net, facebook.com, google.com, twitter.com, and youtube.com show up in the blocked cookie list.

Particular interesting tidbit from the House proceedings was the “Facebook Pixel” – so named because of the single transparent pixel served from a Facebook site if the actual script-based tracking is blocked by the browser. It’s a little code snippet with a function that allows the site owner to track specific actions within the site (i.e. there’s a difference between “someone who visited my site two months ago and has not been back”, “someone who visits my site every other day”, and “someone who spent 100 bucks at my site”) using the standard events (currently nine) and a custom catch-all event. Advertisers then have target audiences created for their custom site data — this means the advertiser cannot see that I visited their site twice a week or spent over ten bucks in the past quarter but they can elect to spend money on ads delivered to people who have visited their site twice in the past week or not deliver ads to people who purchased merchandise in the last month.

Looking through the developer documentation, that is a LOT of really personal information about me that I am not consenting to provide Facebook (in fact, they’re getting that information for people who aren’t even account holders – just their “match pixel to user” algorithm falls out and creates some phantom profile to track the individual instead of landing on a known user’s account). And it’s a lot of really personal information over which I have no control. There’s a difference between opting out of interest based advertising and opting out of tracking. And how exactly can I go about

In the particular case of the Facebook pixel, the script function is housed on a Facebook server. You can pretty easily prevent this bit of tracking. Add a line in your hosts file (/etc/hosts, c:\windows\system32\drivers\etc\hosts) to map the hosting server to your loopback address:

127.0.0.1 connect.facebook.net

Voila, fbq is no longer a valid function. I haven’t noticed any adverse impact to actual Facebook use (although I assume were a significant number of people to block their script host … they’d move it over to a URI that impacted site usage).

Facebook’s debugging tool, meant for advertisers and their developers, confirms the code failed to execute. Browser specific if the <noscript> content is loaded or not – it’s not in my case.

The same approach can be used to block a number of tracking services – script content served from dedicated servers don’t impact general web usability.

127.0.0.1 connect.facebook.net
127.0.0.1 www.google-analytics.com
127.0.0.1 disqus.com
127.0.0.1 cse.google.com
127.0.0.1 bat.bing.com
127.0.0.1 www.googleadservices.com
127.0.0.1 sjs.bizographics.com
127.0.0.1 www.googletagmanager.com
127.0.0.1 chimpstatic.com
127.0.0.1 cdnjs.cloudflare.com
127.0.0.1 api.cartstack.com
127.0.0.1 js-agent.newrelic.com
127.0.0.1 se.monetate.net
127.0.0.1 assets.adobetm.com
127.0.0.1 tribl.io