wiki:Proxies

Proxies

GlimmerBlocker is itself an http proxy and it supports forwarding the requests to other proxies in addition to contacting the web-servers directly.

Feature list:

  1. optional http proxy
  2. optional socks proxy
  3. optional different dns server (when not using proxy)

Proxy usage can be:

  1. static: always use no proxy / same proxy.
  2. network dependent: use company proxy at work, and no proxy at home.
  3. rule based (i.e. URL dependent). You can make some URLs resolve using a different dns server, or using a different http/socks proxy than all other requests.

Case 1: No proxy

This is by far the most comment case. GlimmerBlocker always contacts the web servers directly.

Case 2: Using a single proxy

This is the case when you e.g. have a work computer which you never bring home and the company requires use of a proxy. GlimmerBlocker will always use this proxy.

Case 3: Location-dependent proxy setup

Suppose you have a MacBook which you bring to work. At work it must use a company-wide proxy, but at home it must contact the servers directly. You can write a small Javascript (see examples below) which determines which proxy (if any) that should be used by examining the Network Location, AirPort network name and/or ip-adresses.

Network dependent can check Network location name, AirPort network name, IP adresses, ethernet plugged in, etc. Use MarcoPolo to automatically switch Network Location.

Case 4: URL-dependent proxy setup

This is the most advanced case. In addition to case 3, you can create rules for specific hosts, so accessing some hosts will use one proxy, other hosts will use another proxy, and the remaining some other proxy. Just like you can block ads using host/path/query criterias, you can specify a request-specific proxy.

Case 5: all combinations

You can use both socks and http proxies at the same time.

How to configure

Select the "Network" tab in the GlimmerBlocker Preferences Pane. To never use a proxy (case 1), select "None". To always use the same proxy (case 2), select "Always use this proxy" and enter the name and port-number of the proxy. To use location-dependent proxy (case 3), select "Dynamic configuration".

URL-dependent proxies (case 4) are created as rules, and matching rules overrides any proxy which is setup in the "Network" tab.

The proxy Javascript

The dynamic configurations are created by writing a small Javascript. Select "Dynamic configuration" and click the "edit" button.

The script specifies the configuration by assigning to the variables:

  • gb.network.httpProxy specifies the http proxy. Empty/null means "use no http proxy".
  • gb.network.socksProxy specifies the socks proxy. Empty/null means "use no socks proxy".
  • gb.network.dnsServers specifies the dns servers. Empty/null means "use native OS X resolver".

The variables will be empty when the script is executed, so if the script doesn't assign any value to a variable, the defaults are used. It does not 'remember' the assignment made in previous executions of the script.

The script is executed whenever the network state changes: ethernet plug connected/disconnected, AirPort connected/disconnected to base station, VPN connected/disconnected, IP address changes, ..., i.e. whenever anything in the JSON dump changes.

This network settings Javascript runs globally and does therefore not have access to any request specific information such as URLs. To create request-specific settings, create rules with action = 'modify request'.

The ObjectReference page documents useful utilities such as the gb.log(...) function which logs to the GlimmerBlocker log.

Examples:

gb.network.httpProxy = 'proxy.company.com:8080';
gb.network.socksProxy = 'socks.company.com:1234';

or different DNS server:

gb.network.dnsServers = "8.8.8.8, 8.8.4.4"; // use Google DNS

or

gb.network.dnsServers = "208.67.222.222, 208.67.220.220"; // use OpenDNS

The network state

The second tab in the editing sheet shows the current network state as a JSON dump. A shortened example:

gb.network = {
   location: 'At work',
   interfaces: {
      en0: {},
      en1: {
         link: true,
         AirPort: {
            power: 1,
            ssid: 'The Great Company',
         },
         IPv4: {
            addr: ['10.0.1.123'],
            mask: ['255.255.255.0'],
            broadcast: ['10.0.0.255']
         }
      }
   }
}

The "en0" interface is Ethernet and contains an empty {} object as it isn't connected. The "en1" interface is the AirPort card. The "link" attribute is present and true when the interface is connected, e.g. the Ethernet cable is plugged in or the AirPort is connected to a network.

Simple "use proxy at work" script

Suppose you must use a proxy when having selected the "At work" location, but not when using "Automatic" or "At home". The simple script is:

if (gb.network.location == 'At work')
  gb.network.httpProxy = 'proxy.company.com:8008';

Beware: The above location-name comparison is case-sensitive. Make sure you have the exact name and doesn't have extra spaces in the location name.

When writing a script for the first time, a good idea is to add some debug logging:

if (gb.network.location == 'At work') {
  gb.log("Is at work");
  gb.network.httpProxy = 'proxy.company.com:8008';
} else {
  gb.log("Unknown location, uses no proxy for: %s", gb.network.location);
}

You can view the log by clicking on "Show log" in the "server log" section in the "Developer" tab. You don't need to check "Enable debug logging..." as gb.log(...) will write to the log no matter if it is checked or not.

AirPort network dependent

When AirPort is online, the JSON can look like:

gb.network = {
   interfaces: {
      en1: {
         link: true,
         AirPort: {
            power: 1,
            ssid: 'The Great Company',
         },
         IPv4: { /* ... */ }
      }
   }
}

When it's offline, the JSON can look like:

gb.network = {
   interfaces: {
      en1: {
         AirPort: {
            power: 0
         },
         IPv4: { /* ... */ }
      }
   }
}

The script would be:

if (gb.network.interfaces.en1.AirPort.ssid == 'The Great Company')
  gb.network.httpProxy = 'proxy.company.com:8008';

If you have several AirPort cards installed, you might be advanced:

for (var k in gb.network.interfaces) {
   var x = gb.network.interfaces[k];
   if (!x.AirPort)
      continue;
   if (x.AirPort.ssid == 'The Great Company')
      gb.network.httpProxy = 'proxy.company.com:8008';
}

As most interfaces don't have an AirPort member, the code must check for its presence to avoid dereferencing a null before checking the ssid field.

Detecting IP adresses

Suppose you use Ethernet both at work and home, and doesn't use AirPort, but your IP-address differs.

for (var k in gb.network.interfaces) {
   var x = gb.network.interfaces[k];
   if (!x.IPv4)
      continue;
   if (x.IPv4.addr.length && x.IPv4.addr[0] == '10.0.1.123')
      gb.network.httpProxy = 'proxy.company.com:8008';
}

An interface can have multiple IP adresses, but the above code assumes it has just a single address.

Watching changes as they happend

Go to the "Developer" tab, and check the 2 checkboxes:

  • Enable debug logging...
  • network config

Then click the "Show log" button. The log will show a reduced JSON dump using the unix diff tool as the full dump is too verbose. If you really want the full dump, check the "verbose" checkbox.

GlimmerBlocker is notified by changes to the network state by running a command line tool in the background. You can watch the output by executing the following command in Terminal.App:

/Library/PreferencePanes/GlimmerBlocker.prefPane/Contents/Resources/DebugNetworkState.sh

Hit ctrl-c to stop the command, or just close the window.

URL-specific proxies

URL-specific proxies are specified by creating rules just like the transformation rules. The difference is that the 'modify request' scripts are executed before the request is sent to the server, while the transform scripts are executed after the request is sent to the server and the response is received.

Suppose you want to use a proxy to access your university, but not for all other sites. Assuming the domain name of the university is "ruc.dk", create a rule like:

The default value for the gb.network.httpProxy variable is the output from the global proxy script/settings (if any). So if you don't assign anything to gb.network.httpProxy, the global default is used. If you assign an empty string, the request will not use a proxy, even if a global proxy is configured.

So the rules have the ability to change which proxy is used for the request, but rules doesn't have to specify a proxy. You can e.g. have if (...) gb.network.httpProxy = '...'; conditionals inside the rule's script.

Last modified 5 years ago Last modified on 12/03/09 20:38:58

Attachments (7)

Download all attachments as: .zip