16:01:35 #startmeeting tor anti-censorship meeting 16:01:35 Meeting started Thu Aug 20 16:01:35 2026 UTC. The chair is Shelikhoo[mds]. Information about MeetBot at https://wiki.debian.org/MeetBot. 16:01:35 Useful Commands: #action #agreed #help #info #idea #link #topic. 16:01:35 here is our meeting pad: https://pad.riseup.net/p/r.9574e996bb9c0266213d38b91b56c469 16:01:35 editable link available on request 16:01:50 Hello! 16:01:52 hello 16:02:06 hi~ 16:02:27 hi! 16:03:20 I didn't see any new discussion topic, but we do have a reading group this week 16:03:52 do we need to discuss the snowflake broker deployment? 16:04:02 i saw an announcement last week on that topic 16:04:05 we can discuss if needed 16:04:26 yes, 16:04:28 I have finished running usermode probetest on broker. I will adjust nginx to route traffic to it next Tuesday (https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/work_items/40551) 16:04:28 i saw you opened an issue for the new probetest deployment this morning 16:04:51 yes, sorry it took a while 16:05:03 oh no problem, there's no rush 16:05:08 and the new version of probetest is already running at broker 16:05:21 my question was on plans for the broker update 16:05:31 but did not receive traffic as of now, since nginx config change is not applied 16:05:46 I intent to switch it on next Tuesday 16:05:51 and whether it will include just the NAT bucket changes or also the proxy rate limiting feature 16:06:21 as in, the broker binary itself 16:06:34 I think we should make a single deployment that includes both features, but happy to change that if necessary 16:06:54 ok that sounds good to me 16:07:00 here are the relevant MRs: 16:07:04 https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/merge_requests/727 16:07:18 https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/merge_requests/728 16:07:49 that proxy rate limiting feature i am more nervous about because i think it will impact the proxy pool size and capacity 16:08:11 so i want to be around and watching it when we deploy it so we can update the poll interval, which is currently still manual 16:08:36 so just requesting a heads up whenever that deployment happens 16:08:59 that's it from me 16:09:02 yes! I will let you know before I actually deploy it. 16:09:18 thank you! 16:09:25 nice! 16:10:28 okay we can start the reading group for the paper 16:10:33 https://www.petsymposium.org/popets/2026/popets-2026-0096.pdf 16:10:42 CensorLess: Cost-Efficient Censorship Circumvention 16:10:43 Through Serverless Cloud Functions 16:11:09 anyone wish to share a summary of the paper? 16:11:21 i have one prepared that i can share 16:11:54 nice! 16:12:04 also, DayeonKang[mds], one of the authors is here :) 16:12:07 welcome! 16:12:13 <3 16:12:34 Hello! Thank you for introducing me :) 16:12:35 i'm cecylia btw 16:13:21 ok 16:13:32 CensorLess is a cloud-based circumvention system that uses serverless computing, also called FaaS) to run ultra lightweight HTTP proxies. 16:13:35 It is offered as a successor to SpotProxy, https://censorbib.nymity.ch/#Kon2024b, with simpler deployment and migration, and lower estimated costs. 16:13:38 The client runs a local proxy, the concept of which is similar to how a Tor PT client process works. The CensorLess local proxy repackages requests as HTTP requests to an initial proxy URL that is obtained out of band. 16:13:42 The local proxy then passes HTTP responses back to the client application. 16:13:44 This local proxy also watches for migration tags that indicate a change to the proxy URL. This is distinct from IP rotation, which happens automatically by the cloud provider, without the need to change the URL. 16:13:48 The system can function as either an HTTP proxy, or in private mode as an HTTPS tunnel. 16:13:51 It is possible to use domain fronting techniques with AWS Lambda, https://docs.aws.amazon.com/lambda/latest/dg/welcome.html, one FaaS provider, with some interesting properties: the client can use a different front for each HTTP request, and the fronts do not have to be valid URLs, they just need to match the permitted cloud domain pattern. 16:13:56 16:14:32 nice! thanks for the summary! 16:15:17 is a pretty nice paper, the idea is pretty cool and it looks like is not that expensive to run (compared with many other cloud services) 16:16:05 the downside compared to spotproxy is that in our usecase we would need to develop a new PT for it, I dont' think we can use it direclty with any existing PTs, as we could with spotproxy for snowflake 16:16:12 yeah i really enjoyed reading this paper, and i think there is potential for us to use this with some of our tools 16:16:24 actually it can be used as a signaling channel 16:16:31 like how it was used in geph 16:16:32 https://github.com/geph-official/geph5/blob/master/binaries/geph5-client/src/broker/aws_lambda.rs 16:16:35 meskio[mds]: i was thinking this would be a lower cost and simpler alternative to SQS rendezvous 16:16:49 i wrote up some analysis here: https://gitlab.torproject.org/tpo/research/-/work_items/19 16:16:59 yes, using AWS domain fronting, makes sense 16:17:04 and looks easier to set up 16:17:44 my immediate take is that the obvious thing to do is to make a meek-like tunnel 16:17:53 I guess for this we will not need function rotation 16:17:55 so way simpler to set up 16:18:12 just like meek had php/wsgi/appenengine alternatives for the reflector, e.g., https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/meek/-/tree/v0.38.0/php 16:18:19 dcf1: yeah! that was my other thought, that as a standalone PT it would be a nice alternative to meek 16:18:33 totally 16:18:40 but on that note, i have some clarification questions: 16:18:42 there could be a lambda reflector (even if it maybe cannot be made 100% compatible because of serverless APIs or whatever) 16:19:01 i have a lot of questions and observations too, cohosh go ahead 16:19:44 - do we need to do migration if domain fronting is an option? 16:20:12 getting that initial serverless URL into the hands of users is tricky with the migration feature 16:20:27 or is there a static initial URL that remains the same even if the migration feature is on? 16:20:48 and the initial serverless URL, the paper seems to contradict itself on that point, DayeonKang[mds] maybe you can clarify 16:20:52 4.4 "the local proxy server is preconfigured with an initial serverless bridge URL" 16:20:55 but 16:20:58 4.5 "upon registration, the operator randomly selects the next serverless bridge from the available pool and allocates it to the client" 16:21:05 there are actually 2 ways to use aws lambda, the first way is use xxxxxxx.lambda-url.eu-west-1.on.aws , which basically supports all http request 16:21:24 and can be used as an drop in replacement for any reflector 16:21:41 it's clear there is some kind of initial rendezvous/bootstrapping step, which is necessary because the operator needs to know which clients are live in order to maintain the client–function mapping DB, and also for client and VPS to exchange keys in private mode 16:21:46 In our experiment, we used the static serverless URL address for the initial step, and migrate bridges from the same URL. 16:21:52 however it would require domain fronting to avoid block by sni 16:21:59 does the initial serverless URL also come out of this rendezvous process, or is it preconfigured as stated? 16:22:18 the other choice is to call aws domain directly 16:22:57 like lambda.us-west-1.amazonaws.com 16:23:16 which do not include user id in sni 16:23:35 however requires a custom calling convention 16:23:54 Shelikhoo[mds]: that's interesting. From the source code, censorless seems to be using the first option e.g. 'https://7we6n6kmkv7uc6p7zvvjntkmqa0zelbp.lambda-url.us-east-1.on.aws/' https://bitbucket.org/umass-lab/censorless/src/842c2e4458042d210c15f516fdc5fbb902a6f315/censorless-vanilla/local-proxy/src/proxy.ts#lines-168 16:24:30 Shelikhoo[mds]: thanks for those details, so that second option would be to use the AWS API if i'm understanding that right, like how we do with SQS 16:24:37 dcf1: My tool and I think geph uses the second option: https://github.com/xiaokangwang/lambdaProxy/blob/master/cli/forwarder.go 16:24:45 Shelikhoo[mds]: wait, that is very intriguing, if there's a way of accessing lambda that does not put the user ID in the domain name, even if it requires different techniques to access 16:24:50 https://github.com/geph-official/geph5/blob/master/binaries/geph5-client/src/broker/aws_lambda.rs 16:24:57 hmm very interesting 16:25:35 yeah that's cool 16:25:41 DayeonKang[mds]: okay, so the experimental evaluation was not complete in that sense, it still had a static preconfigured URL that might be blocked in practice 16:26:05 DayeonKang[mds]: what about the private mode key exchange? is that in the source code? did you just do it manually for your experiments? 16:26:22 (cohosh sorry if I'm intruding on your sequence of questions) 16:26:40 Here's the private mode code: https://bitbucket.org/umass-lab/censorless/src/main/censorless-private/ 16:26:43 nope you're good :) 16:26:44 (DayeonKang[mds] some of my questions might be better offline and I can contact you separately) 16:26:59 sounds godd! 16:27:37 cohosh: yes, it would like how sqs works 16:28:01 I was thinking of how to distribute initial serverless URL address becuase of the privacy. Initial thought on the paper was providing temporary urls, which are changing for each users, by embedding in the program 16:28:27 s/users/user/ 16:28:37 * sounds good! 16:30:00 as for the cost, I think the traffic cost is high enough for AWS in general, we might wants to use it as a signaling channel instead of payload channel 16:30:53 since the aws egress cost is a little high for free proxy services 16:30:58 cohosh's investigation at https://gitlab.torproject.org/tpo/research/-/work_items/19 says lambda is only 50% of the cost of SQS per request, and SQS is already a non-trivial cost even though it's used only for Snowflake rendezvous, not the main data channel 16:31:09 DayeonKang[mds]: something like push notifications could be good for this kind of scenario: where there is changing initial connection information that only requires unidirectional information from the tool operators to the client 16:31:15 I got the impresion from the paper that they charge per requests and not per traffic, but maybe I missunderstood 16:31:34 dcf1: well, the per API use cost is 50%, SQS uses a lot more API calls for each rendezvous message 16:31:41 aws charges per request and per traffic 16:31:45 oh 16:31:49 aws lambda charges per request and per traffic 16:32:24 yeah that was another question i had, which is how much the GPS-second cost factors into using AWS lambda 16:32:40 https://aws.amazon.com/lambda/pricing/ 16:33:36 The difference with meek is that when the lambda function is idle waiting for server response, the cost for compute is still ticking 16:33:50 and it will not accept another request to process 16:33:54 Shelikhoo[mds]: by charing per traffic, you mean this compute cost, right? 16:34:17 s/charing/charging 16:34:33 cohosh: compute cost + traffic cost stacked together 16:34:34 i'm curious if that is negligible compared to the per request cost 16:34:40 Data Transfer 16:34:40 Data transferred “in” to and “out” of your AWS Lambda functions, from outside the region the function executed, will be charged at the Amazon EC2 data transfer rates as listed under "Data transfer". 16:35:01 so there is also an data transfer cost 16:36:42 Shelikhoo[mds]: oh i missed that 16:36:45 cohosh: "getting that initial serverless URL into the hands of users is tricky" yes and that point would basically preclude its use as a rendezvous technique, because you would need some other bootstrap channel to bootstrap the serverless channel (to find out the initial URL) 16:37:11 so Shelikhoo[mds]'s lambda.us-west-1.amazonaws.com way seems like it would be better in that regard 16:37:21 dcf1: yeah, although with the use of domain fronting or using API calls instead of direct URL access, we can get around that 16:37:42 I'm not sure that domain fronting alone is a fix, but I have to understand it better. 16:38:31 If we embed a static xyz123.lambda-url.us-east-1.on.aws domain name in clients, it's like, how do we choose that domain in the first place, and what makes it not get blocked 16:38:50 or do we dynamically and independently generate them at each client (maybe the paper said something about that?) 16:39:33 on the note of domain fronting, there was an interesting observation in the paper that the chosen URL doesn't need to match a valid URL that corresponds to an existing serverless instance 16:39:57 and that a different front can be used per request 16:40:12 6.4.1 "we followed the serverless function's URL-generation rule; a string of fixed length randomly mixed with letters and numbers for a unique URL, particularly in AWS Lambda." 16:40:18 is what I was thinking of 16:40:40 okay, so maybe domain fronting is sufficient if the client can generate its own front domains 16:41:15 that's pretty cool 16:42:10 I should note here that if we generate a url that do not exist, and server response a distinct error message for that, a censor can probe if a client is generating random fronting domains 16:42:10 cohosh did you have another in your series of questions? 16:43:00 otherwise I want to quickly share my main observation 16:43:13 go ahead 16:43:38 It looks like both modes of censorless (vanilla and private) are fundamentally request–response oriented 16:44:01 * fronting domains(never mind, aws return AccessDeniedException for unknown url) 16:44:09 vanilla mode operates like a normal HTTP proxy (including doing all the normal HTTP proxy stuff like knowing the difference between hop-by-hop and end-to-end headers, for example https://bitbucket.org/umass-lab/censorless/src/842c2e4458042d210c15f516fdc5fbb902a6f315/censorless-vanilla/local-proxy/src/proxy.ts#lines-42) 16:45:04 private mode has a separate VPS after the serverless bridge, but still (and correct me if I am wrong), what it does is gather up an entire client upstream blob of data, sends it to lambda, and then gathers up a separate downstream blob of data back to the client. 16:45:12 DayeonKang[mds], is my understanding right about this? 16:45:52 In other words, it doesn't seem like you could use censorless, even in private mode, for an interactive TCP protocol like SMTP, where there's intermixed client sending and receiving on one connection. 16:46:13 Yes, right. For the private mode, we used SOCKS proxy and made a longer connection 16:46:44 Okay. There is still a point on that I don't fully understand in section 7, "we employed a custom proxying protocol that persistently tracks connection state across serverless bridge invocations", but I can ask you about that in more detail separately 16:47:18 could do some longpolling, where clients keep always a request open to be able to get data back, but that will make extra request 16:47:20 anyway, it seems like it would be possible to remove most of the complexity from censorless while at the same time remove most of the limitations (including the request–response limitation) 16:48:12 and that's basically to do the meek/champa thing, where between the client and the VPS you have a tunneled encrypted channel (e.g. TLS), and the serverless bridge in the middle just transmits chunks of the that long connection 16:48:49 dcf1: No, lambda do not typically allow streaming response 16:48:51 I.e., the censorless bridge in the middle is not aware of request/response boundaries, that all happens at a different layer. the serverless bridge's only function is "I received a blob of data, forward it and let the endpoints figure it out" 16:48:59 Shelikhoo[mds]: no, you misunderstand 16:49:08 I think that's the same misunderstanding in the paper as well 16:49:17 You don't need streaming responses at the serverless bridge 16:49:30 All you need is individual request–response exchanges 16:49:54 the main point is that those (lambda-layer) request–response exchanged *do not have to match up with* the actual user-layer request–response exchanges 16:50:11 okay, I understand now... 16:50:16 it's the turbo tunnel idea, basically: aws lambda is just a device for carrying bytes from one end to the other 16:50:22 Lambda has an option for streaming response, so we used that mode. but it was quite short streaming 16:50:32 yes.... 16:50:47 the endpoints interpret those bytes however they want, which includes for example reconstructing long-lived stream from them 16:51:34 I think this is a nice idea to bundle data from different connections to a single lambda req-resp by treating the connection as a shared channel 16:51:36 DayeonKang[mds]: the model I think of is: there's a TCP-like "transport layer" between the client and the VPS: it notionally works on streams. The serverless bridge in the middle is more like an "IP layer": it operates on the level of "packets", not on streams. 16:52:00 DayeonKang[mds]: I can elaborate more on this idea in an email. 16:52:38 Sounds good! I have give you my email address 16:52:55 yes, that's great 16:53:15 anyway, this is good work, you can see it has caused a lot of interested discussion 16:53:18 I think v2ray already support this architecture with request transport + req2udp + rrpit... 16:53:31 yeah this is awesome 16:53:37 Shelikhoo[mds]: yes, I could believe that it could be constructed with v2ray already 16:53:39 but anyway, I think lambda is a nice option for signal channel 16:53:47 my email address is dayeonkang@umass.edu / kang.dayeon@me.com 16:55:16 but in any case, some design does not work well in real test, even if perfectly valid otherwise 16:55:48 so I am not sure v2ray's current building block would work well without testing 16:56:08 anyway, anything more we wants to discuss in this meeting? 16:56:12 yeah. DayeonKang[mds] the signaling channel could be an interesting one to pursue, you might want to think about how an ultra-simplified version that just sends 1KB upstream and receives 1KB downstream could work, no sessions, no migration 16:57:07 maybe using the domain name variant that does not embed a user id 16:57:08 yeah i am very interested in the signalling channel, sqs has been great but is tricky to maintain and pay for, this could be a great replacement for that 16:57:12 ok that's all from me for now :) 16:58:12 sorry was trying to get caught up until now, but very nice paper @[Dayeon Kang] :) Thanks for you work on this! 16:58:31 Thank you so much!! 16:59:03 thanks for the nice paper and joining the meeting Dayeon Kang ! 16:59:36 yes, thanks for bringing new ideas 16:59:51 I just added the signaling channel idea to our wiki: https://gitlab.torproject.org/tpo/anti-censorship/team/-/wikis/Signaling-Channels/channels 17:00:18 #endmeeting