Restricting access to AWS EC2 metadata for specific docker containersHow to know if a machine is an EC2 instanceManaging IAM security credentials for multiple docker containersAmazon ECS (Docker): binding container to specific IP addressWhitelisting outgoing traffic from docker containersAWS EC2 Instance Metadata service fails to respondDo we need passwords for localhost database connections in docker context?Locating docker containersConfiguring iptables to let Docker containers access outStarting specific task containers from inside a coordinator containerDocker containers cannot access published ports on host IP
ASCII Meme Arrow Generator
In American Politics, why is the Justice Department under the President?
How can you estimate a spike story?
Can I use 220 V outlets on a 15 ampere breaker and wire it up as 110 V?
Is it safe to dpkg --set-selections on a newer version of a distro?
Was self-modifying code possible using BASIC?
Why would a home insurer offer a discount based on credit score?
Part of my house is inexplicably gone
In The Incredibles 2, why does Screenslaver's name use a pun on something that doesn't exist in the 1950s pastiche?
What do you call the action of "describing events as they happen" like sports anchors do?
Was planting UN flag on Moon ever discussed?
If the pressure inside and outside a balloon balance, then why does air leave when it pops?
Grandpa has another non math question
How to Convert an Object into Array in magento 2
Why are ambiguous grammars bad?
Mathematica 12 has gotten worse at solving simple equations?
How to befriend someone who doesn't like to talk?
Is it true that "only photographers care about noise"?
Print "N NE E SE S SW W NW"
Oil draining out shortly after turbo hose detached/broke
Suppose leased car is totalled: what are financial implications?
How to handle when PCs taste a potion that is actually poison?
Why is it bad to use your whole foot in rock climbing
Are regulatory compliance checks performed within the EU bloc?
Restricting access to AWS EC2 metadata for specific docker containers
How to know if a machine is an EC2 instanceManaging IAM security credentials for multiple docker containersAmazon ECS (Docker): binding container to specific IP addressWhitelisting outgoing traffic from docker containersAWS EC2 Instance Metadata service fails to respondDo we need passwords for localhost database connections in docker context?Locating docker containersConfiguring iptables to let Docker containers access outStarting specific task containers from inside a coordinator containerDocker containers cannot access published ports on host IP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I'm running docker on AWS EC2 instances, and I'd like to block certain containers from accessing
the EC2 instance metadata (at IP address 169.254.169.254). I thought I could do this by running
those containers as a specific user (eg userx), in the presence of the following ip tables rule:
$ iptables -A OUTPUT -m owner --uid-owner userx -d 169.254.169.254 -j DROP
This blocks the connnection as expected when the container is run with host networking:
$ docker run -it --rm --network host -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...blocks..
But sadly allows the connection when the container runs within it's own network
$ docker run -it --rm -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...show metadata...
How can I make this work? Or alternatively, is there some other technique that will give specific containers full network access whilst blocking the instance metadata?
amazon-ec2 iptables docker
add a comment |
I'm running docker on AWS EC2 instances, and I'd like to block certain containers from accessing
the EC2 instance metadata (at IP address 169.254.169.254). I thought I could do this by running
those containers as a specific user (eg userx), in the presence of the following ip tables rule:
$ iptables -A OUTPUT -m owner --uid-owner userx -d 169.254.169.254 -j DROP
This blocks the connnection as expected when the container is run with host networking:
$ docker run -it --rm --network host -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...blocks..
But sadly allows the connection when the container runs within it's own network
$ docker run -it --rm -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...show metadata...
How can I make this work? Or alternatively, is there some other technique that will give specific containers full network access whilst blocking the instance metadata?
amazon-ec2 iptables docker
1
What is your problem, and what are you trying to achieve? Blocking instance metadata isn't an aim or a problem, it's your solution to problem or need you have't stated.
– Tim
Jun 3 at 1:48
My problem is that I have certain containers which need full internet access (as they need to fetch arbitrary public internet URLs). However, if they can access the ec2 metadata, there is the potential to leak privileged information. I need to prevent this.
– timbod
Jun 3 at 3:54
1
Your need for internet access and EC2 metadata seem completely unrelated to me. Can you please edit your post to make it crystal clear the problem you're having or what you're trying to achieve, without making any assumptions around the best solution / implementation.
– Tim
Jun 3 at 5:06
add a comment |
I'm running docker on AWS EC2 instances, and I'd like to block certain containers from accessing
the EC2 instance metadata (at IP address 169.254.169.254). I thought I could do this by running
those containers as a specific user (eg userx), in the presence of the following ip tables rule:
$ iptables -A OUTPUT -m owner --uid-owner userx -d 169.254.169.254 -j DROP
This blocks the connnection as expected when the container is run with host networking:
$ docker run -it --rm --network host -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...blocks..
But sadly allows the connection when the container runs within it's own network
$ docker run -it --rm -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...show metadata...
How can I make this work? Or alternatively, is there some other technique that will give specific containers full network access whilst blocking the instance metadata?
amazon-ec2 iptables docker
I'm running docker on AWS EC2 instances, and I'd like to block certain containers from accessing
the EC2 instance metadata (at IP address 169.254.169.254). I thought I could do this by running
those containers as a specific user (eg userx), in the presence of the following ip tables rule:
$ iptables -A OUTPUT -m owner --uid-owner userx -d 169.254.169.254 -j DROP
This blocks the connnection as expected when the container is run with host networking:
$ docker run -it --rm --network host -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...blocks..
But sadly allows the connection when the container runs within it's own network
$ docker run -it --rm -u $(id -u userx):$(id -g userx) appropriate/curl http://169.254.169.254/latest/meta-data/
...show metadata...
How can I make this work? Or alternatively, is there some other technique that will give specific containers full network access whilst blocking the instance metadata?
amazon-ec2 iptables docker
amazon-ec2 iptables docker
edited May 29 at 0:42
timbod
asked May 27 at 23:40
timbodtimbod
534
534
1
What is your problem, and what are you trying to achieve? Blocking instance metadata isn't an aim or a problem, it's your solution to problem or need you have't stated.
– Tim
Jun 3 at 1:48
My problem is that I have certain containers which need full internet access (as they need to fetch arbitrary public internet URLs). However, if they can access the ec2 metadata, there is the potential to leak privileged information. I need to prevent this.
– timbod
Jun 3 at 3:54
1
Your need for internet access and EC2 metadata seem completely unrelated to me. Can you please edit your post to make it crystal clear the problem you're having or what you're trying to achieve, without making any assumptions around the best solution / implementation.
– Tim
Jun 3 at 5:06
add a comment |
1
What is your problem, and what are you trying to achieve? Blocking instance metadata isn't an aim or a problem, it's your solution to problem or need you have't stated.
– Tim
Jun 3 at 1:48
My problem is that I have certain containers which need full internet access (as they need to fetch arbitrary public internet URLs). However, if they can access the ec2 metadata, there is the potential to leak privileged information. I need to prevent this.
– timbod
Jun 3 at 3:54
1
Your need for internet access and EC2 metadata seem completely unrelated to me. Can you please edit your post to make it crystal clear the problem you're having or what you're trying to achieve, without making any assumptions around the best solution / implementation.
– Tim
Jun 3 at 5:06
1
1
What is your problem, and what are you trying to achieve? Blocking instance metadata isn't an aim or a problem, it's your solution to problem or need you have't stated.
– Tim
Jun 3 at 1:48
What is your problem, and what are you trying to achieve? Blocking instance metadata isn't an aim or a problem, it's your solution to problem or need you have't stated.
– Tim
Jun 3 at 1:48
My problem is that I have certain containers which need full internet access (as they need to fetch arbitrary public internet URLs). However, if they can access the ec2 metadata, there is the potential to leak privileged information. I need to prevent this.
– timbod
Jun 3 at 3:54
My problem is that I have certain containers which need full internet access (as they need to fetch arbitrary public internet URLs). However, if they can access the ec2 metadata, there is the potential to leak privileged information. I need to prevent this.
– timbod
Jun 3 at 3:54
1
1
Your need for internet access and EC2 metadata seem completely unrelated to me. Can you please edit your post to make it crystal clear the problem you're having or what you're trying to achieve, without making any assumptions around the best solution / implementation.
– Tim
Jun 3 at 5:06
Your need for internet access and EC2 metadata seem completely unrelated to me. Can you please edit your post to make it crystal clear the problem you're having or what you're trying to achieve, without making any assumptions around the best solution / implementation.
– Tim
Jun 3 at 5:06
add a comment |
1 Answer
1
active
oldest
votes
Your issue is that OUTPUT doesn't catch packets coming out of containers. FORWARD does.
Why is that?
Every Docker container runs in its own network namespace. Every network namespace has its own routing table and iptables rules, and behaves exactly as if it was a separate physical machine.
In iptables:
INPUTmatches packets going to local processesFORWARDmatches packets coming in one network interface and going out another one (being routed through).OUTPUTmatches packets coming from local processes
The key is that "local process" means "a process in this network namespace", not "a process in this machine".
Let's analyze what's going on:
- Packets are generated by processes in the Docker container's network namespace.
- They go through the iptables
OUTPUTchain in the container's network namespace iptables. (which is empty!) - They get routed out of the
vethinterface. - They arrive to the host's network namespace from the
vethinterface. - The host network namespace consults the routing table and decides they need to go out of e.g.
eth0. - They go through the iptables
FORWARDchain in the host's network namespace. - They go out
eth0.
Therefore, the solution is putting your rule in the FORWARD chain instead.
The issue is that -m owner doesn't work in FORWARD. According to man iptables-extensions:
This match is only valid in the OUTPUT and POSTROUTING chains. Forwarded packets do not have any socket associated with them.
You can either hardcode the container's IP addresses, or put containers you want filtered in a special network, and match the whole range. Something similar to this should work:
# single container
iptables -A FORWARD -s 172.17.0.4 -d 169.254.169.254 -j DROP
# or entire network
iptables -A FORWARD -s 172.17.0.0/16 -d 169.254.169.254 -j DROP
Also, using owner is probably not a good idea either way, because processes inside docker containers can change their uid's via eg setuid binaries (like sudo), if there are any in the image.
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "2"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fserverfault.com%2fquestions%2f969051%2frestricting-access-to-aws-ec2-metadata-for-specific-docker-containers%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your issue is that OUTPUT doesn't catch packets coming out of containers. FORWARD does.
Why is that?
Every Docker container runs in its own network namespace. Every network namespace has its own routing table and iptables rules, and behaves exactly as if it was a separate physical machine.
In iptables:
INPUTmatches packets going to local processesFORWARDmatches packets coming in one network interface and going out another one (being routed through).OUTPUTmatches packets coming from local processes
The key is that "local process" means "a process in this network namespace", not "a process in this machine".
Let's analyze what's going on:
- Packets are generated by processes in the Docker container's network namespace.
- They go through the iptables
OUTPUTchain in the container's network namespace iptables. (which is empty!) - They get routed out of the
vethinterface. - They arrive to the host's network namespace from the
vethinterface. - The host network namespace consults the routing table and decides they need to go out of e.g.
eth0. - They go through the iptables
FORWARDchain in the host's network namespace. - They go out
eth0.
Therefore, the solution is putting your rule in the FORWARD chain instead.
The issue is that -m owner doesn't work in FORWARD. According to man iptables-extensions:
This match is only valid in the OUTPUT and POSTROUTING chains. Forwarded packets do not have any socket associated with them.
You can either hardcode the container's IP addresses, or put containers you want filtered in a special network, and match the whole range. Something similar to this should work:
# single container
iptables -A FORWARD -s 172.17.0.4 -d 169.254.169.254 -j DROP
# or entire network
iptables -A FORWARD -s 172.17.0.0/16 -d 169.254.169.254 -j DROP
Also, using owner is probably not a good idea either way, because processes inside docker containers can change their uid's via eg setuid binaries (like sudo), if there are any in the image.
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
add a comment |
Your issue is that OUTPUT doesn't catch packets coming out of containers. FORWARD does.
Why is that?
Every Docker container runs in its own network namespace. Every network namespace has its own routing table and iptables rules, and behaves exactly as if it was a separate physical machine.
In iptables:
INPUTmatches packets going to local processesFORWARDmatches packets coming in one network interface and going out another one (being routed through).OUTPUTmatches packets coming from local processes
The key is that "local process" means "a process in this network namespace", not "a process in this machine".
Let's analyze what's going on:
- Packets are generated by processes in the Docker container's network namespace.
- They go through the iptables
OUTPUTchain in the container's network namespace iptables. (which is empty!) - They get routed out of the
vethinterface. - They arrive to the host's network namespace from the
vethinterface. - The host network namespace consults the routing table and decides they need to go out of e.g.
eth0. - They go through the iptables
FORWARDchain in the host's network namespace. - They go out
eth0.
Therefore, the solution is putting your rule in the FORWARD chain instead.
The issue is that -m owner doesn't work in FORWARD. According to man iptables-extensions:
This match is only valid in the OUTPUT and POSTROUTING chains. Forwarded packets do not have any socket associated with them.
You can either hardcode the container's IP addresses, or put containers you want filtered in a special network, and match the whole range. Something similar to this should work:
# single container
iptables -A FORWARD -s 172.17.0.4 -d 169.254.169.254 -j DROP
# or entire network
iptables -A FORWARD -s 172.17.0.0/16 -d 169.254.169.254 -j DROP
Also, using owner is probably not a good idea either way, because processes inside docker containers can change their uid's via eg setuid binaries (like sudo), if there are any in the image.
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
add a comment |
Your issue is that OUTPUT doesn't catch packets coming out of containers. FORWARD does.
Why is that?
Every Docker container runs in its own network namespace. Every network namespace has its own routing table and iptables rules, and behaves exactly as if it was a separate physical machine.
In iptables:
INPUTmatches packets going to local processesFORWARDmatches packets coming in one network interface and going out another one (being routed through).OUTPUTmatches packets coming from local processes
The key is that "local process" means "a process in this network namespace", not "a process in this machine".
Let's analyze what's going on:
- Packets are generated by processes in the Docker container's network namespace.
- They go through the iptables
OUTPUTchain in the container's network namespace iptables. (which is empty!) - They get routed out of the
vethinterface. - They arrive to the host's network namespace from the
vethinterface. - The host network namespace consults the routing table and decides they need to go out of e.g.
eth0. - They go through the iptables
FORWARDchain in the host's network namespace. - They go out
eth0.
Therefore, the solution is putting your rule in the FORWARD chain instead.
The issue is that -m owner doesn't work in FORWARD. According to man iptables-extensions:
This match is only valid in the OUTPUT and POSTROUTING chains. Forwarded packets do not have any socket associated with them.
You can either hardcode the container's IP addresses, or put containers you want filtered in a special network, and match the whole range. Something similar to this should work:
# single container
iptables -A FORWARD -s 172.17.0.4 -d 169.254.169.254 -j DROP
# or entire network
iptables -A FORWARD -s 172.17.0.0/16 -d 169.254.169.254 -j DROP
Also, using owner is probably not a good idea either way, because processes inside docker containers can change their uid's via eg setuid binaries (like sudo), if there are any in the image.
Your issue is that OUTPUT doesn't catch packets coming out of containers. FORWARD does.
Why is that?
Every Docker container runs in its own network namespace. Every network namespace has its own routing table and iptables rules, and behaves exactly as if it was a separate physical machine.
In iptables:
INPUTmatches packets going to local processesFORWARDmatches packets coming in one network interface and going out another one (being routed through).OUTPUTmatches packets coming from local processes
The key is that "local process" means "a process in this network namespace", not "a process in this machine".
Let's analyze what's going on:
- Packets are generated by processes in the Docker container's network namespace.
- They go through the iptables
OUTPUTchain in the container's network namespace iptables. (which is empty!) - They get routed out of the
vethinterface. - They arrive to the host's network namespace from the
vethinterface. - The host network namespace consults the routing table and decides they need to go out of e.g.
eth0. - They go through the iptables
FORWARDchain in the host's network namespace. - They go out
eth0.
Therefore, the solution is putting your rule in the FORWARD chain instead.
The issue is that -m owner doesn't work in FORWARD. According to man iptables-extensions:
This match is only valid in the OUTPUT and POSTROUTING chains. Forwarded packets do not have any socket associated with them.
You can either hardcode the container's IP addresses, or put containers you want filtered in a special network, and match the whole range. Something similar to this should work:
# single container
iptables -A FORWARD -s 172.17.0.4 -d 169.254.169.254 -j DROP
# or entire network
iptables -A FORWARD -s 172.17.0.0/16 -d 169.254.169.254 -j DROP
Also, using owner is probably not a good idea either way, because processes inside docker containers can change their uid's via eg setuid binaries (like sudo), if there are any in the image.
edited Jun 4 at 20:01
answered Jun 3 at 21:57
DirbaioDirbaio
1863
1863
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
add a comment |
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
Thanks - this is really helpful answer. One question though - in the above you say "the solution is putting your rule in the FILTER chain", yet your examples add rules to the "FORWARD" chain. Is this difference intentional?
– timbod
Jun 3 at 22:44
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
@timbod My bad, I meant the FORWARD chain. "filter" is the table, not a chain. Fixed! :)
– Dirbaio
Jun 4 at 20:02
add a comment |
Thanks for contributing an answer to Server Fault!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fserverfault.com%2fquestions%2f969051%2frestricting-access-to-aws-ec2-metadata-for-specific-docker-containers%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
What is your problem, and what are you trying to achieve? Blocking instance metadata isn't an aim or a problem, it's your solution to problem or need you have't stated.
– Tim
Jun 3 at 1:48
My problem is that I have certain containers which need full internet access (as they need to fetch arbitrary public internet URLs). However, if they can access the ec2 metadata, there is the potential to leak privileged information. I need to prevent this.
– timbod
Jun 3 at 3:54
1
Your need for internet access and EC2 metadata seem completely unrelated to me. Can you please edit your post to make it crystal clear the problem you're having or what you're trying to achieve, without making any assumptions around the best solution / implementation.
– Tim
Jun 3 at 5:06