1 <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML
4.0//EN'
>
4 Copyright (C) 2006-2008 Jonathan Zarate
5 http://www.polarcloud.com/tomato/
7 Portions Copyright (C) 2008-2009 Keith Moyer, tomatovpn@keithmoyer.com
9 For use with Tomato Firmware only.
10 No part of this file may be used without permission.
14 <meta http-equiv='content-type' content='text/html;charset=utf-
8'
>
15 <meta name='robots' content='noindex,nofollow'
>
16 <title>[<%
ident(); %>] VPN: Client
</title>
17 <link rel='stylesheet' type='text/css' href='tomato.css'
>
18 <link rel='stylesheet' type='text/css' href='color.css'
>
19 <script type='text/javascript' src='tomato.js'
></script>
20 <script type='text/javascript'
>
22 // <% nvram("vpn_client1_if,vpn_client1_bridge,vpn_client1_nat,vpn_client1_proto,vpn_client1_addr,vpn_client1_port,vpn_client1_retry,vpn_client1_firewall,vpn_client1_crypt,vpn_client1_comp,vpn_client1_cipher,vpn_client1_local,vpn_client1_remote,vpn_client1_nm,vpn_client1_hmac,vpn_client1_custom,vpn_client1_static,vpn_client1_ca,vpn_client1_crt,vpn_client1_key,vpn_client2_if,vpn_client2_bridge,vpn_client2_nat,vpn_client2_proto,vpn_client2_addr,vpn_client2_port,vpn_client2_retry,vpn_client2_firewall,vpn_client2_crypt,vpn_client2_comp,vpn_client2_cipher,vpn_client2_local,vpn_client2_remote,vpn_client2_nm,vpn_client2_hmac,vpn_client2_custom,vpn_client2_static,vpn_client2_ca,vpn_client2_crt,vpn_client2_key"); %>
24 tabs
= [['client1', 'Client 1'],['client2', 'Client 2']];
25 ciphers
= [['default','Use Default'],['none','None']<% vpnciphers(); %>];
28 vpn1up
= parseInt('<% psup("vpnclient1"); %>');
29 vpn2up
= parseInt('<% psup("vpnclient2"); %>');
31 function tabSelect(name
)
35 for (var i
= 0; i
< tabs
.length
; ++i
)
37 var on
= (name
== tabs
[i
][0]);
38 elem
.display(tabs
[i
][0] + '-tab', on
);
41 cookie
.set('vpn_client_tab', name
);
44 function toggle(service
, isup
)
46 if (changed
&& !confirm("Unsaved changes will be lost. Continue anyway?")) return;
48 E('_' + service
+ '_button').disabled
= true;
49 form
.submitHidden('service.cgi', {
50 _redirect
: 'vpn-client.asp',
52 _service
: service
+ (isup
? '-stop' : '-start')
56 function verifyFields(focused
, quiet
)
60 // When settings change, make sure we restart the right client
65 var clientindex
= focused
.name
.indexOf("client");
68 var clientnumber
= focused
.name
.substring(clientindex
+6,clientindex
+7);
69 var stripped
= focused
.name
.substring(0,clientindex
+6)+focused
.name
.substring(clientindex
+7);
71 if (stripped
== 'vpn_client_local')
72 E('_f_vpn_client'+clientnumber
+'_local').value
= focused
.value
;
73 else if (stripped
== 'f_vpn_client_local')
74 E('_vpn_client'+clientnumber
+'_local').value
= focused
.value
;
76 if (eval('vpn'+clientnumber
+'up') && fom
._service
.value
.indexOf('client'+clientnumber
) < 0)
79 if ( fom
._service
.value
!= "" ) fom
._service
.value
+= ",";
80 fom
._service
.value
+= 'vpnclient'+clientnumber
+'-restart';
85 // Element varification
86 for (i
= 0; i
< tabs
.length
; ++i
)
90 if (!v_ip('_vpn_'+t
+'_addr', true) && !v_domain('_vpn_'+t
+'_addr', true)) { ferror
.set(E('_vpn_'+t
+'_addr'), "Invalid server address.", quiet
); ret
= 0; }
91 if (!v_port('_vpn_'+t
+'_port', quiet
)) ret
= 0;
92 if (!v_ip('_vpn_'+t
+'_local', quiet
, 1)) ret
= 0;
93 if (!v_ip('_f_vpn_'+t
+'_local', true, 1)) ret
= 0;
94 if (!v_ip('_vpn_'+t
+'_remote', quiet
, 1)) ret
= 0;
95 if (!v_netmask('_vpn_'+t
+'_nm', quiet
)) ret
= 0;
96 if (!v_range('_vpn_'+t
+'_retry', quiet
, -1, 32767)) ret
= 0;
100 for (i
= 0; i
< tabs
.length
; ++i
)
104 fw
= E('_vpn_'+t
+'_firewall');
105 auth
= E('_vpn_'+t
+'_crypt');
106 iface
= E('_vpn_'+t
+'_if');
107 bridge
= E('_f_vpn_'+t
+'_bridge');
108 nat
= E('_f_vpn_'+t
+'_nat');
109 hmac
= E('_vpn_'+t
+'_hmac');
111 elem
.display(PR('_vpn_'+t
+'_ca'), PR('_vpn_'+t
+'_crt'), PR('_vpn_'+t
+'_key'), PR('_vpn_'+t
+'_hmac'), auth
.value
== "tls");
112 elem
.display(PR('_vpn_'+t
+'_static'), auth
.value
== "secret" || (auth
.value
== "tls" && hmac
.value
>= 0));
113 elem
.display(E(t
+'_custom_crypto_text'), auth
.value
== "custom");
114 elem
.display(PR('_f_vpn_'+t
+'_bridge'), iface
.value
== "tap");
115 elem
.display(E(t
+'_bridge_warn_text'), !bridge
.checked
);
116 elem
.display(PR('_f_vpn_'+t
+'_nat'), fw
.value
!= "custom" && (iface
.value
== "tun" || !bridge
.checked
));
117 elem
.display(E(t
+'_nat_warn_text'), fw
.value
!= "custom" && (!nat
.checked
|| (auth
.value
== "secret" && iface
.value
== "tun")));
118 elem
.display(PR('_vpn_'+t
+'_local'), auth
.value
== "secret" && iface
.value
== "tun");
119 elem
.display(PR('_f_vpn_'+t
+'_local'), auth
.value
== "secret" && (iface
.value
== "tap" && !bridge
.checked
));
127 if (!verifyFields(null, false)) return;
131 for (i
= 0; i
< tabs
.length
; ++i
)
135 E('vpn_'+t
+'_bridge').value
= E('_f_vpn_'+t
+'_bridge').checked
? 1 : 0;
136 E('vpn_'+t
+'_nat').value
= E('_f_vpn_'+t
+'_nat').checked
? 1 : 0;
145 <style type='text/css'
>
154 <form id='_fom' method='post' action='tomato.cgi'
>
155 <table id='container' cellspacing=
0>
156 <tr><td colspan=
2 id='header'
>
157 <div class='title'
>Tomato
</div>
158 <div class='version'
>Version <%
version(); %></div>
160 <tr id='body'
><td id='navi'
><script type='text/javascript'
>navi()</script></td>
162 <div id='ident'
><%
ident(); %></div>
164 <input type='hidden' name='_nextpage' value='vpn-client.asp'
>
165 <input type='hidden' name='_nextwait' value='
5'
>
166 <input type='hidden' name='_service' value=''
>
168 <div class='section-title'
>VPN Client Configuration
</div>
169 <div class='section'
>
170 <script type='text/javascript'
>
171 tabCreate
.apply(this, tabs
);
173 for (i
= 0; i
< tabs
.length
; ++i
)
176 W('<div id=\''+t
+'-tab\'>');
177 W('<input type=\'hidden\' id=\'vpn_'+t
+'_bridge\' name=\'vpn_'+t
+'_bridge\'>');
178 W('<input type=\'hidden\' id=\'vpn_'+t
+'_nat\' name=\'vpn_'+t
+'_nat\'>');
179 createFieldTable('', [
180 { title
: 'Interface Type', name
: 'vpn_'+t
+'_if', type
: 'select', options
: [ ['tap','TAP'], ['tun','TUN'] ], value
: eval( 'nvram.vpn_'+t
+'_if' ) },
181 { title
: 'Protocol', name
: 'vpn_'+t
+'_proto', type
: 'select', options
: [ ['udp','UDP'], ['tcp-client','TCP'] ], value
: eval( 'nvram.vpn_'+t
+'_proto' ) },
182 { title
: 'Server Address/Port', multi
: [
183 { name
: 'vpn_'+t
+'_addr', type
: 'text', size
: 17, value
: eval( 'nvram.vpn_'+t
+'_addr' ) },
184 { name
: 'vpn_'+t
+'_port', type
: 'text', maxlen
: 5, size
: 7, value
: eval( 'nvram.vpn_'+t
+'_port' ) } ] },
185 { title
: 'Firewall', name
: 'vpn_'+t
+'_firewall', type
: 'select', options
: [ ['auto', 'Automatic'], ['custom', 'Custom'] ], value
: eval( 'nvram.vpn_'+t
+'_firewall' ) },
186 { title
: 'Authorization Mode', name
: 'vpn_'+t
+'_crypt', type
: 'select', options
: [ ['tls', 'TLS'], ['secret', 'Static Key'], ['custom', 'Custom'] ], value
: eval( 'nvram.vpn_'+t
+'_crypt' ),
187 suffix
: '<span id=\''+t
+'_custom_crypto_text\'> <small>(configured below...)</small></span>' },
188 { title
: 'Extra HMAC authorization (tls-auth)', name
: 'vpn_'+t
+'_hmac', type
: 'select', options
: [ [-1, 'Disabled'], [2, 'Bi-directional'], [0, 'Incoming (0)'], [1, 'Outgoing (1)'] ], value
: eval( 'nvram.vpn_'+t
+'_hmac' ) },
189 { title
: 'Server is on the same subnet', name
: 'f_vpn_'+t
+'_bridge', type
: 'checkbox', value
: eval( 'nvram.vpn_'+t
+'_bridge' ) != 0,
190 suffix
: '<span style="color: red" id=\''+t
+'_bridge_warn_text\'> <small>Warning: Cannot bridge distinct subnets. Defaulting to routed mode.<small></span>' },
191 { title
: 'Create NAT on tunnel', name
: 'f_vpn_'+t
+'_nat', type
: 'checkbox', value
: eval( 'nvram.vpn_'+t
+'_nat' ) != 0,
192 suffix
: '<span style="font-style: italic" id=\''+t
+'_nat_warn_text\'> <small>Routes must be configured manually.<small></span>' },
193 { title
: 'Local/remote endpoint addresses', multi
: [
194 { name
: 'vpn_'+t
+'_local', type
: 'text', maxlen
: 15, size
: 17, value
: eval( 'nvram.vpn_'+t
+'_local' ) },
195 { name
: 'vpn_'+t
+'_remote', type
: 'text', maxlen
: 15, size
: 17, value
: eval( 'nvram.vpn_'+t
+'_remote' ) } ] },
196 { title
: 'Tunnel address/netmask', multi
: [
197 { name
: 'f_vpn_'+t
+'_local', type
: 'text', maxlen
: 15, size
: 17, value
: eval( 'nvram.vpn_'+t
+'_local' ) },
198 { name
: 'vpn_'+t
+'_nm', type
: 'text', maxlen
: 15, size
: 17, value
: eval( 'nvram.vpn_'+t
+'_nm' ) } ] },
199 { title
: 'Encryption cipher', name
: 'vpn_'+t
+'_cipher', type
: 'select', options
: ciphers
, value
: eval( 'nvram.vpn_'+t
+'_cipher' ) },
200 { title
: 'Compression', name
: 'vpn_'+t
+'_comp', type
: 'select', options
: [ ['yes', 'Enabled'], ['no', 'Disabled'], ['adaptive', 'Adaptive'] ], value
: eval( 'nvram.vpn_'+t
+'_comp' ) },
201 { title
: 'Connection retry', name
: 'vpn_'+t
+'_retry', type
: 'text', maxlen
: 5, size
: 7, value
: eval( 'nvram.vpn_'+t
+'_retry' ),
202 suffix
: ' <small>(in seconds; -1 for infinite)</small>' },
203 { title
: 'Custom Configuration', name
: 'vpn_'+t
+'_custom', type
: 'textarea', value
: eval( 'nvram.vpn_'+t
+'_custom' ) },
204 { title
: 'Static Key', name
: 'vpn_'+t
+'_static', type
: 'textarea', value
: eval( 'nvram.vpn_'+t
+'_static' ) },
205 { title
: 'Certificate Authority', name
: 'vpn_'+t
+'_ca', type
: 'textarea', value
: eval( 'nvram.vpn_'+t
+'_ca' ) },
206 { title
: 'Client Certificate', name
: 'vpn_'+t
+'_crt', type
: 'textarea', value
: eval( 'nvram.vpn_'+t
+'_crt' ) },
207 { title
: 'Client Key', name
: 'vpn_'+t
+'_key', type
: 'textarea', value
: eval( 'nvram.vpn_'+t
+'_key' ) }
209 W('<input type="button" value="' + (eval('vpn'+(i
+1)+'up') ? 'Stop' : 'Start') + ' Now" onclick="toggle(\'vpn'+t
+'\', vpn'+(i
+1)+'up)" id="_vpn'+t
+'_button">');
217 <tr><td id='footer' colspan=
2>
218 <span id='footer-msg'
></span>
219 <input type='button' value='Save' id='save-button' onclick='save()'
>
220 <input type='button' value='Cancel' id='cancel-button' onclick='javascript:reloadPage();'
>
224 <script type='text/javascript'
>tabSelect(cookie
.get('vpn_client_tab') || tabs
[0][0]); verifyFields(null, 1);</script>