Category Archives: HOWTO

Articles that describe in a concise manner how to achieve a certain objective. E.g. how to install some software or how to configure software to do X or Y.

Hacking the Safari search engine

How to use Apache to change the search engine used by the Safari search box.

Introduction

On my Mac I prefer to use the Safari web browser, because it is fast and well integrated into the system. However there is one thing I don’t like… I don’t have any choice to which search engine I use with the search field in the browser.
There are several existing hacks to change the search engine, but either they change the Safari binary, which does not play well with codesigning, or they work with plugins that use undocumented and unsupported hooks in the browser or system.
I wanted to do it in a way that does not break when I update Safari.

The fix

When looking at the problem I quickly realised that it is very easy to recognize the requests that Safari makes, because the query string contains the parameter client=safari. So the idea was born to rewrite the request so the searches are redirected to lxquick.com, while everything else still goes to Google. With Apache 2.2 every Mac has the tool to make this happen.

Implementation

First make sure that Apache is running by checking ‘Webserver’ in the ‘Sharing’ System Preference.

Next you need to make a couple of files and place all of them in the /etc/apache2/other directory. To write in this directory you need to have admin privileges, since we need to do several things on the command line as root we start with a sudo -s to get a root shell.

First, create /etc/apache2/other/search.conf. I will explain some of the code here in the following section.

<VirtualHost *:80>
  ServerName www.google.com

  RewriteEngine On
  RewriteCond %{QUERY_STRING} client=safari
  RewriteCond %{QUERY_STRING} q=([^&]*)
  RewriteRule ^/search http://ixquick.com/do/metasearch.pl?query=%1

  ProxyPass / http://www.l.google.com/
  ProxyPassReverse / http://www.l.google.com/
  ProxyPreserveHost On
</VirtualHost>

Listen *:443

<VirtualHost *:443>
  ServerName www.google.com
  ProxyPass / https://www.l.google.com/
  ProxyPassReverse / https://www.l.google.com/
  ProxyPreserveHost On
  SSLEngine On
  SSLProxyEngine On
  SSLCertificateFile /etc/apache2/other/server.crt
  SSLCertificateKeyFile /etc/apache2/other/server.key
</VirtualHost>

Second, create a self signed certificate for www.google.com.

openssl genrsa 1024 > /etc/apache2/other/server.key
openssl req -new -key /etc/apache2/other/server.key -x509 -days 1000000 -out /etc/apache2/other/server.crt

OpenSSL will ask you a couple of questions for the second command. Most of these questions are not really of importance, since we are creating a self signed certificate. Only you do want the Common Name attribute to be www.google.com, otherwise the browser will always ask you for permission to use the certificate.

Now the Apache configuration is ready. You can have Apache test your configuration with the following command:

apachectl configtest

If everything is okay you can restart Apache with the command:

apachectl restart

Now you only have to fool the system so it will redirect requests for http://www.google.com to your apache install. Luckily this is really easy. We just have to edit the file /etc/hosts and add www.google.com at the end of the line starting with 127.0.0.1, so it should read:

##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost www.google.com
255.255.255.255	broadcasthost
::1             localhost
fe80::1%lo0	localhost

Finish everything by restarting Safari and browse to https://www.google.com/. You will get a certificate warning, because we use a self signed certificate. Select to trust the certificate permanently and you’re good to go.

The magic

There are three pieces of magic at work here.

  1. The hosts files allows us to override the DNS for www.google.com
  2. The proxy module in Apache allows us to act as a proxy for www.google.com
  3. The rewrite engine of Apache makes it possible to change just the requests from the Safari search box and send them to lxquick.com

Point 2 & 3 need some explanation.

proxying for www.google.com

The following three lines in the configuration are at the heart of our tip.

  ProxyPass / http://www.l.google.com/
  ProxyPassReverse / http://www.l.google.com/
  ProxyPreserveHost On

ProxyPass and ProxyPassReverse make sure that the requests are sent to Google, and the last makes sure that we tell the Google servers that we want pages for www.google.com. Google makes it very easy for us, because www.google.com is a CNAME for www.l.google.com. This allows us to refer to exactly the same servers with a different name.

Rewriting the requests

The rewrite engine allows us to rewrite a request only if it meets specific conditions. In our case the browser makes a request for http://www.google.com/search?client=safari&rls=en&q=bla&ie=UTF-8&oe=UTF-8. In the code below the conditions are specified with the RewriteCond and what we want to do is specified in the RewriteRule.

 RewriteEngine On
  RewriteCond %{QUERY_STRING} client=safari
  RewriteCond %{QUERY_STRING} q=([^&]*)
  RewriteRule ^/search http://ixquick.com/do/metasearch.pl?query=%1

We use two conditions to work our magic. The first is that the URL must match client=safari in the query string. The second one is that we must have a search term specified with q=. In this second condition we have some additional magic. The parenthesis tell the rewrite engine that we want to refer back to the result of the expression within the rewrite rule. Between the parenthesis we have a rule that says that we want take all of the query string till the next occurrence of the & or the end of the line.
In the Rewrite rule we tell that we want to rewrite request that start with /search and meet the two conditions above. Of course we also need to specify how we want to rewrite them. Here we put the URL that lxquick expects for a search request. The %1 here is special, because it refers back to the data that matched with our expression within the parenthesis in our second rewrite condition.