feat: add --refrag for dummy TLS record injection
This commit is contained in:
parent
85f80ef4af
commit
40052c65fa
3 changed files with 52 additions and 0 deletions
25
README.md
25
README.md
|
|
@ -22,6 +22,8 @@ ihtc [flags]
|
|||
--min-chunk int Minimum bytes per fragment (default 3)
|
||||
--max-chunk int Maximum bytes per fragment (default 8)
|
||||
--delay-us int Max microsecond delay between fragments (default 500)
|
||||
--refrag int Dummy TLS records before ClientHello (default 1, disabled)
|
||||
--regex string Only fragment hosts matching this regex
|
||||
--verbose Enable debug logging
|
||||
--auto-proxy Set macOS auto proxy configuration
|
||||
```
|
||||
|
|
@ -41,8 +43,31 @@ When a browser opens an HTTPS connection through the proxy:
|
|||
|
||||
- TCP only (no QUIC/HTTP3)
|
||||
- Not effective against DPIs that perform TCP stream reassembly
|
||||
- For reassembling DPIs, see [re-fragmentation](#re-fragmentation)
|
||||
- No authentication (local-only, trusted environment)
|
||||
|
||||
## Advanced
|
||||
|
||||
### Fragmenting only blocked domains
|
||||
|
||||
Use `--regex` to limit fragmentation to specific hosts. All other traffic passes through unfragmented:
|
||||
|
||||
```sh
|
||||
./ihtc --auto-proxy --regex 'discord\.com|discord\.gg|twitter\.com'
|
||||
```
|
||||
|
||||
### Re-fragmentation
|
||||
|
||||
For DPIs that reassemble TCP streams, enable re-fragmentation with `--refrag N`:
|
||||
|
||||
```sh
|
||||
./ihtc --refrag 3
|
||||
```
|
||||
|
||||
This inserts N-1 deliberately invalid TLS records before the real ClientHello, each in its own TCP segment. A reassembling DPI must inspect multiple nearly-identical records and choose the correct one — while the TLS server ignores the invalid records and processes only the final valid one.
|
||||
|
||||
Set N based on DPI aggressiveness (2-5 is typical). Higher values add latency with diminishing returns.
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE](LICENSE).
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ func main() {
|
|||
verbose := flag.Bool("verbose", false, "Enable debug logging")
|
||||
autoProxy := flag.Bool("auto-proxy", false, "Set macOS auto proxy configuration")
|
||||
hostRegex := flag.String("regex", "", "Only proxy hosts matching this regex")
|
||||
refrag := flag.Int("refrag", 1, "Number of dummy TLS records before ClientHello (1 = disabled)")
|
||||
flag.Parse()
|
||||
|
||||
logger := log.New(*verbose)
|
||||
|
|
@ -35,11 +36,16 @@ func main() {
|
|||
logger.Error("max-chunk must be >= min-chunk")
|
||||
os.Exit(1)
|
||||
}
|
||||
if *refrag < 1 {
|
||||
logger.Error("refrag must be >= 1")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfg := obfuscate.Config{
|
||||
MinChunk: *minChunk,
|
||||
MaxChunk: *maxChunk,
|
||||
DelayUs: *delayUs,
|
||||
Refrag: *refrag,
|
||||
}
|
||||
|
||||
p := proxy.New(*listen, cfg, logger, *autoProxy)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ type Config struct {
|
|||
MinChunk int
|
||||
MaxChunk int
|
||||
DelayUs int
|
||||
Refrag int
|
||||
}
|
||||
|
||||
func Split(data []byte, cfg Config) [][]byte {
|
||||
|
|
@ -81,6 +82,15 @@ func HandleClientHello(dst net.Conn, src io.Reader, cfg Config) (int, error) {
|
|||
}
|
||||
|
||||
fullHello := append(header, body...)
|
||||
|
||||
dummyRecords := buildDummyRecords(cfg.Refrag)
|
||||
for _, d := range dummyRecords {
|
||||
chunks := Split(d, cfg)
|
||||
if err := writeFragmented(dst, chunks, cfg); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
chunks := Split(fullHello, cfg)
|
||||
if err := writeFragmented(dst, chunks, cfg); err != nil {
|
||||
return len(fullHello), err
|
||||
|
|
@ -88,3 +98,14 @@ func HandleClientHello(dst net.Conn, src io.Reader, cfg Config) (int, error) {
|
|||
|
||||
return len(fullHello), nil
|
||||
}
|
||||
|
||||
func buildDummyRecords(count int) [][]byte {
|
||||
if count <= 1 {
|
||||
return nil
|
||||
}
|
||||
records := make([][]byte, count-1)
|
||||
for i := range records {
|
||||
records[i] = []byte{0x17, 0x03, 0x03, 0x00, 0x00}
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue