first commit

This commit is contained in:
Jakob
2025-11-15 18:46:07 +01:00
commit c23257cde3
8 changed files with 318 additions and 0 deletions

0
README.md Normal file
View File

BIN
de.webproxy Executable file

Binary file not shown.

23
demo.crt Normal file
View File

@@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIUNs/bkWG+0hoVIpnfHEAFvyiPQAIwDQYJKoZIhvcNAQEL
BQAwfjELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxFzAVBgNVBAcMDkhh
bHRlcm4gQW0gU2VlMRAwDgYDVQQKDAdKYWtvYnVzMRIwEAYDVQQDDAlyaXNjaC5k
ZXYxHjAcBgkqhkiG9w0BCQEWD2pha29iQHJpc2NoLmRldjAeFw0yNTExMTUxNjAy
NTlaFw0zNTExMTMxNjAyNTlaMH4xCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdHZXJt
YW55MRcwFQYDVQQHDA5IYWx0ZXJuIEFtIFNlZTEQMA4GA1UECgwHSmFrb2J1czES
MBAGA1UEAwwJcmlzY2guZGV2MR4wHAYJKoZIhvcNAQkBFg9qYWtvYkByaXNjaC5k
ZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz4AUvRbxSWud+NKLW
ZOG3W8BZrg1n5kEWjKnQ1fqFD/4aloHUMS3eCkg3gbOfVXQMMcPxkGeE8ewi3/Y1
69mXI2EXu2JOBLmA4egcB5RJv8ROO5jSd4B/DmZVT95w3QEvUagKEJ8riHLO6hum
rXtDUZxmTwgOjNGGi90t1eQA/POm7epTfaOvyIAgG+iUde5qDEkA2fdjDhYnf4kG
iTiobyaVtT3L5XmYrfrKkcpZL/sPT7EL/K8DR2s51d1vo9iK7as6bn0rQzRMlj9A
TqpUlJPiuR4noNHd0/4Vqm+k9e1mA2QT2qbSKJW/twGtOzhSjNr9c+KqD8IfmTdD
djZ/AgMBAAGjUzBRMB0GA1UdDgQWBBTENgOWRTm0w7oRqgRKlWVLhBHAZDAfBgNV
HSMEGDAWgBTENgOWRTm0w7oRqgRKlWVLhBHAZDAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQARccbOzDTd8Rlc3LNU4LlXhBvFio5Nd/+9/gnDpYaV
z12Ym+aHslfveu2wqyLTOKrXyORijaxCL9QN88o48sYWMx7Z2DBrgpbH7KqZOdLK
WnQ1mZGrfd5Ts3uzqNW6ZG0ewhzX1JGHHxX1u0lRsR6kGTeSQcxcXkqVEklQnAcO
NzJYsfV7hegKDJiQEsquvNxjiS7PgFm+Ee+zPNe7JZedfAKTMSxNSk80c8xN2Tm3
qaz76FakgMUf6mvvdR7bXiF8Efxz7RgkJxlGEEtzs9fOYYcViTdGmARPv/DHWg9d
XxhL7WbR4XCeESk5WVRou00+p/o62HpIhspYzWhFWTJS
-----END CERTIFICATE-----

28
demo.key Normal file
View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz4AUvRbxSWud+
NKLWZOG3W8BZrg1n5kEWjKnQ1fqFD/4aloHUMS3eCkg3gbOfVXQMMcPxkGeE8ewi
3/Y169mXI2EXu2JOBLmA4egcB5RJv8ROO5jSd4B/DmZVT95w3QEvUagKEJ8riHLO
6humrXtDUZxmTwgOjNGGi90t1eQA/POm7epTfaOvyIAgG+iUde5qDEkA2fdjDhYn
f4kGiTiobyaVtT3L5XmYrfrKkcpZL/sPT7EL/K8DR2s51d1vo9iK7as6bn0rQzRM
lj9ATqpUlJPiuR4noNHd0/4Vqm+k9e1mA2QT2qbSKJW/twGtOzhSjNr9c+KqD8If
mTdDdjZ/AgMBAAECggEAGsHJaPxJz223/4VAmdLSOW57wPthVszLbtlyzglz5YT5
ACcrszmzldLYEPBex2YJ8rcZFjSBvvwma75UB4uzckZFhFG6sFoHPDLz+O4Zsr9v
f1G3NyD8ANUkB4RvgEDSkyGQSnBUNRYW5KJc2vZLHpBOdcZDhQ0718oIwe+OJfqQ
NP6+jzOZaimdxsvY7EmmW71YlMlChTSf1VbSYTuc4DLDtMmhRBdQeACuPbiAFqNO
qpaEO4mZ6E9UnZw79TKepL/0viBnqZB0AavPdp88Feg8euwu/z7mGji45etq7c7L
QZNjuaMUnh3T+miRjgJjWOxk/QSdqwSjdZzDIx9mSQKBgQDf59T/QJqm25ESD0AH
ck9HlMPsDCZiMru+o+rIqCu4TmiV/fcA869JHeYNDYQR7jPqaL6Uxfx2EvddeyVj
rxR+eAnW6ycqsfNsbNAF13qZdYsPNhLOfBVbIcIt9p+H088U2sQ7lWml+Q+SXz7p
7uPHOYu7IIhuRP/pmyN/r7sepwKBgQDNqH9121/Ktcol5ez3+KZ1HRNGfwBpAOta
8RsHPeDEAW9zzVoXUXjIMvCN9re1Neq0MGuZWKUn3jNT49v8YvFQGluyFSLV7zNs
RwyXieNp3ZJCU1LP9ElWZbBjC0qfuoX17on8Uf01oiEPK398W/zoMI/F5mjq/Pch
uhJXC6y8aQKBgQCkMiKkvP+sdT/BeqV90HoLCDFVHOPZB1Nezl4SoCDPm9Bejktg
y1Mzz1UxJURA0eoIcJ+yAi7Nd8MnLnOQ0oe45tZwYSnryWu1i2ZRol8pwmUj1oec
HKqclfkMM9txhAZMSNG20C8Vo7ujn21HqAQpyS2LIKRsGPWCnl49+OTD6QKBgG2f
4cF7HIa7fHPTKgvMWT6YLwwm6psOSGaDmvqzOzp/4V8DGYDQhueAb8Xcu3Q2t1Mx
dEmbfP3Rbd7L2RmhzCv8wOAecCFFjk2rWcT1VWm7GBmOvNfoyabqMam5/R9Dl+DO
NHNxaN3L/H9Pmnc5uYgzSpAdD9Qi38D0pI4NxRfxAoGAIv7GlbBktH/EvlxeZ8dX
RCl5iyHJ8ke6mXaG4cNceoWy8pGw1GquJmnW1jZK3mCtTQ0kE0z89VyKreMcB8Gh
AS2DqwJ2MY3z7m9RXqreLQuzeTHQPOU6GcP9V+m88OT6IoeoraHMuzawp/C5hack
tOyj0B3anEXqdaXYgenMoPw=
-----END PRIVATE KEY-----

10
go.mod Normal file
View File

@@ -0,0 +1,10 @@
module de.webproxy
go 1.25.4
require (
github.com/AdguardTeam/golibs v0.4.0 // indirect
github.com/AdguardTeam/gomitmproxy v0.2.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/text v0.3.2 // indirect
)

23
go.sum Normal file
View File

@@ -0,0 +1,23 @@
github.com/AdguardTeam/golibs v0.4.0 h1:4VX6LoOqFe9p9Gf55BeD8BvJD6M6RDYmgEiHrENE9KU=
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
github.com/AdguardTeam/gomitmproxy v0.2.1 h1:p9gr8Er1TYvf+7ic81Ax1sZ62UNCsMTZNbm7tC59S9o=
github.com/AdguardTeam/gomitmproxy v0.2.1/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

183
main.go Normal file
View File

@@ -0,0 +1,183 @@
package main
import (
"bytes"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"io"
"net"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/gomitmproxy"
"github.com/AdguardTeam/gomitmproxy/mitm"
"github.com/AdguardTeam/gomitmproxy/proxyutil"
_ "net/http/pprof"
)
func main() {
log.SetLevel(log.DEBUG)
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// Read the MITM cert and key.
tlsCert, err := tls.LoadX509KeyPair("demo.crt", "demo.key")
if err != nil {
log.Fatal(err)
}
privateKey := tlsCert.PrivateKey.(*rsa.PrivateKey)
x509c, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
log.Fatal(err)
}
mitmConfig, err := mitm.NewConfig(x509c, privateKey, &CustomCertsStorage{
certsCache: map[string]*tls.Certificate{}},
)
if err != nil {
log.Fatal(err)
}
// Generate certs valid for 7 days.
mitmConfig.SetValidity(time.Hour * 24 * 7)
// Set certs organization.
mitmConfig.SetOrganization("Jakobus")
// Generate a cert-key pair for the HTTP-over-TLS proxy.
/*proxyCert, err := mitmConfig.GetOrCreateCert("127.0.0.1")
if err != nil {
panic(err)
}
/*tlsConfig := &tls.Config{
Certificates: []tls.Certificate{*proxyCert},
}*/
// Prepare the proxy.
addr := &net.TCPAddr{
IP: net.IPv4(0, 0, 0, 0),
Port: 3333,
}
proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
ListenAddr: addr,
MITMConfig: mitmConfig,
MITMExceptions: []string{"example.com"},
OnRequest: onRequest,
OnResponse: onResponse,
OnConnect: onConnect,
})
err = proxy.Start()
if err != nil {
log.Fatal(err)
}
signalChannel := make(chan os.Signal, 1)
signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)
<-signalChannel
// Stop the proxy.
proxy.Close()
}
func onRequest(session *gomitmproxy.Session) (*http.Request, *http.Response) {
req := session.Request()
log.Printf("onRequest: %s %s", req.Method, req.URL.String())
if req.URL.Host == "testgomitmproxy" {
body := strings.NewReader("<html><body><h1>Served by gomitmproxy</h1></body></html>")
res := proxyutil.NewResponse(http.StatusOK, body, req)
res.Header.Set("Content-Type", "text/html")
return nil, res
}
return nil, req.Response
}
func onResponse(session *gomitmproxy.Session) *http.Response {
log.Printf("onResponse: %s", session.Request().URL.String())
if _, ok := session.GetProp("blocked"); ok {
log.Printf("onResponse: was blocked")
return nil
}
res := session.Response()
req := session.Request()
if strings.Index(res.Header.Get("Content-Type"), "text/html") != 0 {
// Do nothing with non-HTML responses
return nil
}
b, err := proxyutil.ReadDecompressedBody(res)
// Close the original body.
_ = res.Body.Close()
if err != nil {
return proxyutil.NewErrorResponse(req, err)
}
// Use latin1 before modifying the body. Using this 1-byte encoding will
// let us preserve all original characters regardless of what exactly is
// the encoding.
body, err := proxyutil.DecodeLatin1(bytes.NewReader(b))
if err != nil {
return proxyutil.NewErrorResponse(session.Request(), err)
}
// Modifying the original body.
modifiedBody, err := proxyutil.EncodeLatin1(body + "")
if err != nil {
return proxyutil.NewErrorResponse(session.Request(), err)
}
println("Modified body123:" + string(modifiedBody))
res.Body = io.NopCloser(bytes.NewReader(modifiedBody))
res.Header.Del("Content-Encoding")
res.ContentLength = int64(len(modifiedBody))
return res
}
func onConnect(_ *gomitmproxy.Session, _ string, addr string) (conn net.Conn) {
host, _, err := net.SplitHostPort(addr)
if err == nil && host == "testgomitmproxy" {
// Don't let it connecting there, we'll serve it by ourselves.
return &proxyutil.NoopConn{}
}
return nil
}
// CustomCertsStorage is an example of a custom cert storage.
type CustomCertsStorage struct {
// certsCache is a cache with the generated certificates.
certsCache map[string]*tls.Certificate
}
// Get gets the certificate from the storage.
func (c *CustomCertsStorage) Get(key string) (cert *tls.Certificate, ok bool) {
cert, ok = c.certsCache[key]
return cert, ok
}
// Set saves the certificate to the storage.
func (c *CustomCertsStorage) Set(key string, cert *tls.Certificate) {
c.certsCache[key] = cert
}

51
server.pem Normal file
View File

@@ -0,0 +1,51 @@
-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIUNs/bkWG+0hoVIpnfHEAFvyiPQAIwDQYJKoZIhvcNAQEL
BQAwfjELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxFzAVBgNVBAcMDkhh
bHRlcm4gQW0gU2VlMRAwDgYDVQQKDAdKYWtvYnVzMRIwEAYDVQQDDAlyaXNjaC5k
ZXYxHjAcBgkqhkiG9w0BCQEWD2pha29iQHJpc2NoLmRldjAeFw0yNTExMTUxNjAy
NTlaFw0zNTExMTMxNjAyNTlaMH4xCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdHZXJt
YW55MRcwFQYDVQQHDA5IYWx0ZXJuIEFtIFNlZTEQMA4GA1UECgwHSmFrb2J1czES
MBAGA1UEAwwJcmlzY2guZGV2MR4wHAYJKoZIhvcNAQkBFg9qYWtvYkByaXNjaC5k
ZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz4AUvRbxSWud+NKLW
ZOG3W8BZrg1n5kEWjKnQ1fqFD/4aloHUMS3eCkg3gbOfVXQMMcPxkGeE8ewi3/Y1
69mXI2EXu2JOBLmA4egcB5RJv8ROO5jSd4B/DmZVT95w3QEvUagKEJ8riHLO6hum
rXtDUZxmTwgOjNGGi90t1eQA/POm7epTfaOvyIAgG+iUde5qDEkA2fdjDhYnf4kG
iTiobyaVtT3L5XmYrfrKkcpZL/sPT7EL/K8DR2s51d1vo9iK7as6bn0rQzRMlj9A
TqpUlJPiuR4noNHd0/4Vqm+k9e1mA2QT2qbSKJW/twGtOzhSjNr9c+KqD8IfmTdD
djZ/AgMBAAGjUzBRMB0GA1UdDgQWBBTENgOWRTm0w7oRqgRKlWVLhBHAZDAfBgNV
HSMEGDAWgBTENgOWRTm0w7oRqgRKlWVLhBHAZDAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQARccbOzDTd8Rlc3LNU4LlXhBvFio5Nd/+9/gnDpYaV
z12Ym+aHslfveu2wqyLTOKrXyORijaxCL9QN88o48sYWMx7Z2DBrgpbH7KqZOdLK
WnQ1mZGrfd5Ts3uzqNW6ZG0ewhzX1JGHHxX1u0lRsR6kGTeSQcxcXkqVEklQnAcO
NzJYsfV7hegKDJiQEsquvNxjiS7PgFm+Ee+zPNe7JZedfAKTMSxNSk80c8xN2Tm3
qaz76FakgMUf6mvvdR7bXiF8Efxz7RgkJxlGEEtzs9fOYYcViTdGmARPv/DHWg9d
XxhL7WbR4XCeESk5WVRou00+p/o62HpIhspYzWhFWTJS
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz4AUvRbxSWud+
NKLWZOG3W8BZrg1n5kEWjKnQ1fqFD/4aloHUMS3eCkg3gbOfVXQMMcPxkGeE8ewi
3/Y169mXI2EXu2JOBLmA4egcB5RJv8ROO5jSd4B/DmZVT95w3QEvUagKEJ8riHLO
6humrXtDUZxmTwgOjNGGi90t1eQA/POm7epTfaOvyIAgG+iUde5qDEkA2fdjDhYn
f4kGiTiobyaVtT3L5XmYrfrKkcpZL/sPT7EL/K8DR2s51d1vo9iK7as6bn0rQzRM
lj9ATqpUlJPiuR4noNHd0/4Vqm+k9e1mA2QT2qbSKJW/twGtOzhSjNr9c+KqD8If
mTdDdjZ/AgMBAAECggEAGsHJaPxJz223/4VAmdLSOW57wPthVszLbtlyzglz5YT5
ACcrszmzldLYEPBex2YJ8rcZFjSBvvwma75UB4uzckZFhFG6sFoHPDLz+O4Zsr9v
f1G3NyD8ANUkB4RvgEDSkyGQSnBUNRYW5KJc2vZLHpBOdcZDhQ0718oIwe+OJfqQ
NP6+jzOZaimdxsvY7EmmW71YlMlChTSf1VbSYTuc4DLDtMmhRBdQeACuPbiAFqNO
qpaEO4mZ6E9UnZw79TKepL/0viBnqZB0AavPdp88Feg8euwu/z7mGji45etq7c7L
QZNjuaMUnh3T+miRjgJjWOxk/QSdqwSjdZzDIx9mSQKBgQDf59T/QJqm25ESD0AH
ck9HlMPsDCZiMru+o+rIqCu4TmiV/fcA869JHeYNDYQR7jPqaL6Uxfx2EvddeyVj
rxR+eAnW6ycqsfNsbNAF13qZdYsPNhLOfBVbIcIt9p+H088U2sQ7lWml+Q+SXz7p
7uPHOYu7IIhuRP/pmyN/r7sepwKBgQDNqH9121/Ktcol5ez3+KZ1HRNGfwBpAOta
8RsHPeDEAW9zzVoXUXjIMvCN9re1Neq0MGuZWKUn3jNT49v8YvFQGluyFSLV7zNs
RwyXieNp3ZJCU1LP9ElWZbBjC0qfuoX17on8Uf01oiEPK398W/zoMI/F5mjq/Pch
uhJXC6y8aQKBgQCkMiKkvP+sdT/BeqV90HoLCDFVHOPZB1Nezl4SoCDPm9Bejktg
y1Mzz1UxJURA0eoIcJ+yAi7Nd8MnLnOQ0oe45tZwYSnryWu1i2ZRol8pwmUj1oec
HKqclfkMM9txhAZMSNG20C8Vo7ujn21HqAQpyS2LIKRsGPWCnl49+OTD6QKBgG2f
4cF7HIa7fHPTKgvMWT6YLwwm6psOSGaDmvqzOzp/4V8DGYDQhueAb8Xcu3Q2t1Mx
dEmbfP3Rbd7L2RmhzCv8wOAecCFFjk2rWcT1VWm7GBmOvNfoyabqMam5/R9Dl+DO
NHNxaN3L/H9Pmnc5uYgzSpAdD9Qi38D0pI4NxRfxAoGAIv7GlbBktH/EvlxeZ8dX
RCl5iyHJ8ke6mXaG4cNceoWy8pGw1GquJmnW1jZK3mCtTQ0kE0z89VyKreMcB8Gh
AS2DqwJ2MY3z7m9RXqreLQuzeTHQPOU6GcP9V+m88OT6IoeoraHMuzawp/C5hack
tOyj0B3anEXqdaXYgenMoPw=
-----END PRIVATE KEY-----