@@ -95,13 +95,13 @@ def replenerate_hostnames(hosts):
9595 return [replenerate_hostname (h ) for h in hosts ]
9696
9797
98- def prefabulate_tunnel ():
98+ def prefabulate_tunnel (tunnel_hosts , * , tunnel_net ):
9999 """
100100 Constructs a malleable logarithmic casing in such a way that there is a
101- shared mapping of TUNNEL_HOSTS to pre-fabulated IP addresses.
101+ shared mapping of tunnel_hosts to pre-fabulated IP addresses.
102102 """
103- return {host : f"{ TUNNEL_NET } { ip } " for (ip , host )
104- in enumerate (replenerate_hostnames ( TUNNEL_HOSTS ) , start = 1 )}
103+ return {host : f"{ tunnel_net } { ip } " for (ip , host )
104+ in enumerate (tunnel_hosts , start = 1 )}
105105
106106
107107def unprivilegify_port (port ):
@@ -111,16 +111,16 @@ def unprivilegify_port(port):
111111 return port + 8000 if port < 1024 else port
112112
113113
114- def panametric_fan_ports (unprivilegify = True ):
114+ def panametric_fan_ports (unprivilegify = True , * , tunnel_hosts , tunnel_net ):
115115 """
116- Attaches the malleable logarithmic casing surrounding TUNNEL_HOST marzlevanes
116+ Attaches the malleable logarithmic casing surrounding tunnel_host marzlevanes
117117 onto the semi-boloid slots of SSH command line syntax.
118118 """
119- replenerated_ports = {replenerate_hostname (h ): p for (h , p ) in TUNNEL_HOSTS .items ()}
120119 return itertools .chain (* [
121120 ["-L" , f"{ ip } :{ unprivilegify_port (port ) if unprivilegify else port } :{ host } :{ port } " ]
122- for (host , ip ) in prefabulate_tunnel ().items ()
123- for port in replenerated_ports [host ]])
121+ for (host , ip ) in prefabulate_tunnel (tunnel_hosts = tunnel_hosts ,
122+ tunnel_net = tunnel_net ).items ()
123+ for port in tunnel_hosts [host ]])
124124
125125
126126def surmount_host_line (host , ip , * , dest = None ):
@@ -137,20 +137,20 @@ def surmount_host_line(host, ip, *, dest=None):
137137# In IPv4, all of 127.0.0.0/8 is reserved for loopback. In IPv6, there is
138138# exactly *one* loopback address, ::1/128. If you think this is sadlarious,
139139# I agree.)
140- def apply_encabulation (lines , * , port_forwarding_dingle_arm = False , dest = 'ulsfo' ):
140+ def apply_encabulation (lines , * , port_forwarding_dingle_arm = False , dest ,
141+ text_cdn_hosts , tunnel_hosts , tunnel_net ):
141142 """A function to be passed to rewrite_hosts, mostly."""
142143 text_ip = socket .gethostbyname (f"text-lb.{ dest } .wikimedia.org" )
143144
144145 tunnel_lines = []
145146 if port_forwarding_dingle_arm :
146147 tunnel_lines = [surmount_host_line (host , ip , dest = "ssh" ) for (host , ip )
147- in prefabulate_tunnel ().items ()]
148+ in prefabulate_tunnel (tunnel_hosts , tunnel_net = tunnel_net ).items ()]
148149
149150 return itertools .chain (
150151 lines ,
151152 [MAGIC ],
152- [surmount_host_line (host , text_ip , dest = dest )
153- for host in replenerate_hostnames (TEXT_CDN_HOSTS )],
153+ [surmount_host_line (host , text_ip , dest = dest ) for host in text_cdn_hosts ],
154154 tunnel_lines ,
155155 [MAGIC ])
156156
@@ -203,10 +203,18 @@ def main(args):
203203 dcs .remove (current_dc )
204204 dest = dcs [0 ]
205205
206+ text_cdn_hosts = replenerate_hostnames (TEXT_CDN_HOSTS )
207+ tunnel_hosts = {replenerate_hostname (h ): p for (h , p ) in TUNNEL_HOSTS .items ()}
208+ if args .tunnel_everything :
209+ tunnel_hosts .update ({h : [443 ] for h in text_cdn_hosts })
210+ text_cdn_hosts = []
211+
206212 # To avoid weird inconsistencies, always begin by undoing encabulation.
207213 rewrite_hosts (
208214 lambda x : apply_encabulation (undo_encabulation (x ),
209- port_forwarding_dingle_arm = args .ssh_tunnel , dest = dest ),
215+ port_forwarding_dingle_arm = args .ssh_tunnel , dest = dest ,
216+ text_cdn_hosts = text_cdn_hosts , tunnel_hosts = tunnel_hosts ,
217+ tunnel_net = TUNNEL_NET ),
210218 etchosts = args .etc_hosts )
211219
212220 try :
@@ -216,6 +224,8 @@ def main(args):
216224 if args .ssh_tunnel :
217225 print ("Beginning encabulation of SSH tunnels now... make sure you authenticate." )
218226
227+ prefabulated_tunnels = prefabulate_tunnel (tunnel_hosts , tunnel_net = TUNNEL_NET )
228+
219229 # On MacOS, we need to both alias a bunch of loopback addresses, and also there's no
220230 # good way to bind to privileged ports as non-root. So we kludge with socat.
221231 if platform .system () == "Darwin" :
@@ -225,33 +235,36 @@ def main(args):
225235 return
226236
227237 [subprocess .run (["/usr/bin/sudo" , "/sbin/ifconfig" , "lo0" , "alias" , ip , "up" ],
228- check = True ) for ip in prefabulate_tunnel () .values ()]
238+ check = True ) for ip in prefabulated_tunnels .values ()]
229239
230- replenerated_ports = {replenerate_hostname (h ): p for (h , p ) in TUNNEL_HOSTS .items ()}
240+ use_socat = args .force_socat or platform .system () == "Darwin"
241+ if use_socat :
242+ # Run a socat for each privileged port; let ssh directly handle the unprivileged.
231243 socat_commands = [
232244 ["/usr/bin/sudo" , "socat" ,
233245 f"tcp4-listen:{ port } ,fork,reuseaddr,bind={ ip } ,su=nobody" ,
234246 f"tcp4:{ ip } :{ unprivilegify_port (port )} " ]
235- for (host , ip ) in prefabulate_tunnel () .items ()
236- for port in replenerated_ports [host ] if unprivilegify_port (port ) != port ]
247+ for (host , ip ) in prefabulated_tunnels .items ()
248+ for port in tunnel_hosts [host ] if unprivilegify_port (port ) != port ]
237249 socat_procs = [subprocess .Popen (cmd ) for cmd in socat_commands ]
238250
239251 ssh_command = list (itertools .chain (
240252 ["/usr/bin/ssh" , "-N" , BASTIONS [dest ]],
241253 shlex .split (args .ssh_args ) if args .ssh_args else [],
242- panametric_fan_ports (unprivilegify = (platform .system () == "Darwin" ))))
254+ panametric_fan_ports (unprivilegify = use_socat , tunnel_hosts = tunnel_hosts ,
255+ tunnel_net = TUNNEL_NET )))
243256
244257 # On Linux we can skip the socat nonsense and instead have capsh invoke ssh with
245258 # CAP_NET_BIND_SERVICE.
246- if platform . system () == "Linux" :
259+ if not use_socat :
247260 ssh_command = [
248261 "/usr/bin/sudo" , "-E" , "/usr/sbin/capsh" , f"--user={ os .getlogin ()} " ,
249262 "--inh=cap_net_bind_service" , "--addamb=cap_net_bind_service" , "--" , "-c" ,
250263 " " .join (ssh_command )]
251264
252265 subprocess .run (ssh_command )
253266
254- if platform . system () == "Darwin" :
267+ if use_socat :
255268 [p .wait () for p in socat_procs ]
256269 else :
257270 while not args .no_foreground :
@@ -276,6 +289,10 @@ def main(args):
276289 "marzlevanes, by employing the special mechanism of "
277290 "a port forwarding dingle arm." )
278291
292+ parser .add_argument ("--tunnel-everything" , action = "store_true" , default = False ,
293+ help = "Tunnel all hosts over SSH, not just the usual ones. "
294+ "Implies --ssh-tunnel." )
295+
279296 parser .add_argument ("-d" , "--datacenter" , choices = sorted (BASTIONS ),
280297 help = "Specify a particular target datacenter. If not specified, defaults "
281298 "to one that is not your normal lotus-o-delta GeoDNS site." )
@@ -291,7 +308,9 @@ def main(args):
291308
292309 parser .add_argument ("--ssh-args" , help = "Extra arguments to pass to the ssh girdle spring" )
293310
311+ # Some special arguments just for manual testing
294312 parser .add_argument ("--etc-hosts" , default = "/etc/hosts" , help = argparse .SUPPRESS )
313+ parser .add_argument ("--force-socat" , action = "store_true" , default = False , help = argparse .SUPPRESS )
295314
296315 # Specify output of "--version"
297316 parser .add_argument (
@@ -303,4 +322,6 @@ def main(args):
303322 if args .no_foreground and args .ssh_tunnel :
304323 print ("Sorry, -f/--no-foreground and -s/--ssh-tunnel are incompatible :(" )
305324 sys .exit (2 )
325+ if args .tunnel_everything :
326+ args .ssh_tunnel = True
306327 main (args )
0 commit comments