On Tue, Aug 16, 2011 at 06:53:01AM -0500, Todd T. Fries wrote:
> I have done this in a different way, namely by 'filtering' the variables
> that are passed to /sbin/dhclient-script by using the
> 'script "/path/to/my/script"' option to run my own script, act on variables
> I care about (dns and default gateway) and then calling /sbin/dhclient-script
> in the event it still has something to do.
> 
> Honestly I think your approach is cleaner, and more likely to survive the
> ever eminent promise from krw@ to remove the script entirely.

ouch. and I think you mean imminent. :-)

.... Ken

> 
> Thanks,
> 
> Penned by Stefan Sperling on 20110816  5:08.37, we have:
> | In some networks (e.g. at public events using open wifi) I want
> | traffic not destined for the local network to go through a VPN.
> | 
> | If the local network uses DHCP, I usually end up killing dhclient
> | because it's impossible to renew the lease without changing the
> | default route.
> | 
> | To be clear, I end up with a command sequence like:
> | 
> |  dhclient wpi0  # get a local address
> |  netstat -rn -finet | grep ^default  # figure out local router
> |  route delete default # don't use local router for everything
> |  route add -host $VPN_SERVER_IP $LOCAL_ROUTER # just for this host
> |  openvpn config-file # start VPN, i am too dumb for ipsec
> |  route add default $ROUTER_BEHIND_VPN # use my trusted router as default
> |  pkill -x dhclient # kill dhclient to avoid default route change later
> | 
> | The problem is that the lease expires at some point and things
> | usually stop working until I perform the same tedious configuration
> | dance again.
> | 
> | The patch below adds a new option to dhclient.conf (the VPN server is
> | at 10.1.1.1 in this example):
> | 
> |   interface "wpi0" {
> |           host-route 10.1.1.1;
> |   }
> | 
> | Instead of adding a default route dhclient will add a host route
> | to the specified address. So the above sequence becomes:
> | 
> |  dhclient wpi0  # get a local address, add route to VPN server
> |  openvpn config-file # start VPN
> |  route add default $ROUTER_BEHIND_VPN # use my trusted router as default
> | 
> | And the configuration remains stable.
> | 
> | Is this a good approach?
> | Does anyone else think this is useful?
> | 
> | 
> | Index: clparse.c
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/clparse.c,v
> | retrieving revision 1.37
> | diff -u -p -r1.37 clparse.c
> | --- clparse.c       4 Apr 2011 11:14:52 -0000       1.37
> | +++ clparse.c       12 Aug 2011 18:04:02 -0000
> | @@ -151,7 +151,8 @@ read_client_leases(void)
> |   * interface-declaration |
> |   * TOK_LEASE client-lease-statement |
> |   * TOK_ALIAS client-lease-statement |
> | - * TOK_REJECT reject-statement
> | + * TOK_REJECT reject-statement |
> | + * TOK_HOST_ROUTE host-route-statement
> |   */
> |  void
> |  parse_client_statement(FILE *cfile)
> | @@ -234,6 +235,9 @@ parse_client_statement(FILE *cfile)
> |     case TOK_REJECT:
> |             parse_reject_statement(cfile);
> |             return;
> | +   case TOK_HOST_ROUTE:
> | +           parse_host_route_statement(cfile);
> | +           return;
> |     default:
> |             parse_warn("expecting a statement.");
> |             skip_to_semi(cfile);
> | @@ -739,6 +743,25 @@ parse_reject_statement(FILE *cfile)
> |             token = next_token(&val, cfile);
> |     } while (token == ',');
> |  
> | +   if (token != ';') {
> | +           parse_warn("expecting semicolon.");
> | +           skip_to_semi(cfile);
> | +   }
> | +}
> | +
> | +void
> | +parse_host_route_statement(FILE *cfile)
> | +{
> | +   char *val;
> | +   int token;
> | +
> | +   if (!parse_ip_addr(cfile, &config->host_route)) {
> | +           parse_warn("expecting IP address.");
> | +           skip_to_semi(cfile);
> | +           return;
> | +   }
> | +
> | +   token = next_token(&val, cfile);
> |     if (token != ';') {
> |             parse_warn("expecting semicolon.");
> |             skip_to_semi(cfile);
> | Index: conflex.c
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/conflex.c,v
> | retrieving revision 1.13
> | diff -u -p -r1.13 conflex.c
> | --- conflex.c       17 Dec 2006 17:41:56 -0000      1.13
> | +++ conflex.c       12 Aug 2011 18:00:51 -0000
> | @@ -324,6 +324,7 @@ static const struct keywords {
> |     { "filename",                           TOK_FILENAME },
> |     { "fixed-address",                      TOK_FIXED_ADDR },
> |     { "hardware",                           TOK_HARDWARE },
> | +   { "host-route",                         TOK_HOST_ROUTE },
> |     { "initial-interval",                   TOK_INITIAL_INTERVAL },
> |     { "interface",                          TOK_INTERFACE },
> |     { "lease",                              TOK_LEASE },
> | Index: dhclient-script
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/dhclient-script,v
> | retrieving revision 1.22
> | diff -u -p -r1.22 dhclient-script
> | --- dhclient-script 9 Apr 2011 19:53:00 -0000       1.22
> | +++ dhclient-script 12 Aug 2011 18:06:00 -0000
> | @@ -60,11 +60,16 @@ delete_old_routes() {
> |  add_new_routes() {
> |     route -q $rdomain -n flush -inet -iface $interface
> |     for router in $new_routers; do
> | -           if [ "$new_ip_address" = "$router" ]; then
> | -                   route -q $rdomain add default -iface $router
> | +           if [ -n "$host_route" -a "$host_route" != "0.0.0.0" ]; then
> | +                   new_route="-host $host_route $router"
> |             else
> | -                   route -q $rdomain add default $router
> | +                   if [ "$new_ip_address" = "$router" ]; then
> | +                           new_route="default -iface $router"
> | +                   else
> | +                           new_route="default $router"
> | +                   fi
> |             fi
> | +           route -q $rdomain add $new_route
> |             # 2nd and subsequent default routers error out, so explicitly
> |             # stop processing the list after the first one.
> |             break
> | Index: dhclient.c
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
> | retrieving revision 1.141
> | diff -u -p -r1.141 dhclient.c
> | --- dhclient.c      11 May 2011 14:38:36 -0000      1.141
> | +++ dhclient.c      12 Aug 2011 18:06:57 -0000
> | @@ -1604,6 +1604,9 @@ supersede:
> |     }
> |     snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
> |     script_set_env(prefix, "expiry", tbuf);
> | +
> | +   if (config->host_route.len)
> | +           script_set_env("", "host_route", piaddr(config->host_route));
> |  }
> |  
> |  void
> | Index: dhclient.conf.5
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/dhclient.conf.5,v
> | retrieving revision 1.21
> | diff -u -p -r1.21 dhclient.conf.5
> | --- dhclient.conf.5 9 Apr 2011 19:53:00 -0000       1.21
> | +++ dhclient.conf.5 13 Aug 2011 19:18:56 -0000
> | @@ -430,6 +430,13 @@ If no lease is acquired, the script is u
> |  any, and also called once if no valid lease can be identified.
> |  For more information, see
> |  .Xr dhclient.leases 5 .
> | +.It Ic host-route Ar ip-address ;
> | +The
> | +.Ic host-route
> | +statement causes the DHCP client to install a host route to the specified
> | +IP address instead of installing a default route.
> | +This is useful if the default route points to a VPN tunnel terminated
> | +at the specified IP address instead of a router on the local network.
> |  .El
> |  .Sh EXAMPLES
> |  The following configuration file is used on a laptop
> | Index: dhcpd.h
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/dhcpd.h,v
> | retrieving revision 1.73
> | diff -u -p -r1.73 dhcpd.h
> | --- dhcpd.h 11 May 2011 14:38:36 -0000      1.73
> | +++ dhcpd.h 12 Aug 2011 18:03:23 -0000
> | @@ -150,6 +150,7 @@ struct client_config {
> |     enum { IGNORE, ACCEPT, PREFER }
> |                              bootp_policy;
> |     struct iaddrlist        *reject_list;
> | +   struct iaddr             host_route;
> |  };
> |  
> |  struct client_state {
> | @@ -344,3 +345,4 @@ void parse_client_lease_declaration(FILE
> |  int parse_option_decl(FILE *, struct option_data *);
> |  void parse_string_list(FILE *, struct string_list **, int);
> |  void parse_reject_statement(FILE *);
> | +void parse_host_route_statement(FILE *);
> | Index: dhctoken.h
> | ===================================================================
> | RCS file: /cvs/src/sbin/dhclient/dhctoken.h,v
> | retrieving revision 1.5
> | diff -u -p -r1.5 dhctoken.h
> | --- dhctoken.h      15 May 2006 08:10:57 -0000      1.5
> | +++ dhctoken.h      12 Aug 2011 18:03:38 -0000
> | @@ -79,6 +79,7 @@
> |  #define TOK_REJECT         292
> |  #define TOK_FDDI           293
> |  #define TOK_LINK_TIMEOUT   294
> | +#define TOK_HOST_ROUTE             295
> |  
> |  #define is_identifier(x)   ((x) >= TOK_FIRST_TOKEN &&      \
> |                              (x) != TOK_STRING &&   \
> 
> -- 
> Todd Fries .. [email protected]
> 
>  _____________________________________________
> |                                             \  1.636.410.0632 (voice)
> | Free Daemon Consulting, LLC                 \  1.405.227.9094 (voice)
> | http://FreeDaemonConsulting.com             \  1.866.792.3418 (FAX)
> | 2525 NW Expy #525, Oklahoma City, OK 73112  \  sip:[email protected]
> | "..in support of free software solutions."  \  sip:[email protected]
>  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
>                                                  
>               37E7 D3EB 74D0 8D66 A68D  B866 0326 204E 3F42 004A
>                         http://todd.fries.net/pgp.txt

Reply via email to