I had a similar problem to this, needing to rewrite an outgoing url. In my case it was in a docker container running on kubernetes.
In my case it was because of this issue: https://stackoverflow.com/a/63712440
The app runtime (.net core 3.1) crypto code only checks the first url in the list of certificate revocation endpoints. I was doing an SSL client certificate setup (mTLS).
The PKI cert I was issued contained an internal domain address first+second, and then a publicly addressable url third:
X509v3 CRL Distribution Points:
Full Name:
URI:http://some.domain.1/CRL/Cert.crl
URI:http://some.domain.2/CRL/Cert.crl
URI:http://x509.domain.com/CRL.crl
Because the domain addresses use a 'CRL' folder in the path, but the public url does not, just mapping the public IP address to the local domain host via /etc/hosts (or k8s hostAliases) didn't work.
To solve this in k8s, I added a sidecar to my pod; here's the details:
First, start with an nginx.conf:
events { }
http {
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:5555;
}
location /CRL/ {
proxy_pass http://x509.domain.com/;
}
}
}
This kind of looks like a reverse proxy, but really it just an actual proxy. My dotnet app serves on port 5555 inside the pod. 127.0.0.1 will route to the pod, not the nginx container. Note that the second proxy_pass value doesn't include the 'CRL' path, that allows the url to rewritten not just redirected.
I then built an nginx docker image called crl-rewrite-proxy:
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
I then added the image into my pod yaml as a sidecar:
- name: crl-rewrite-proxy
image: $(image):crl-rewrite-proxy
ports:
- containerPort: 80
And then added an alias for the internal domain address, so outgoing calls to it from the app would route back into the pod:
hostAliases:
- ip: "127.0.0.1"
hostnames:
- "some.domain.1"
Lastly I defined an ingress in my k8s yaml, so the aliased calls will be routed to the sidecar:
- kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: $(name)-crl-rewrite-proxy
namespace: $(namespace)
spec:
rules:
- host: $(name).$(host)
http:
paths:
- path: /CRL
pathType: ImplementationSpecific
backend:
service:
name: $(name)
port:
number: 80
The app runtime makes a call to http://some.domain.1/CRL/Cert.crl; the host alias routes that to 127.0.0.1:80; k8s passes that to the sidecar; the sidecar passes that to nginx; nginx rewrite the host+url to a public IP on a different path; the resource then gets fetched successfully.
Thanks to thor above for the local setup, I used this to verify it would work locally before doing up the k8s bits.