script for connecting to an amazon ec2 instance by public dns - amazon-ec2

I need to write a script that can start an aws instance by its public dns,
I can start the instance at the moment by using a filter with my instance name, but if I try to filter with the {tag:'Public DNS': my_publicdns} I get an error. Is it even possible to filter by public dns?
my_publicdns = 'ec2-1-2-3-4.eu-west-1.compute.amazonaws.com'
myinstance = 'GA_brian_burroughs'
def start_instance():
try:
inst = conn.get_all_instances(filters={'tag:Name': myinstance})[0].instances[0]
except Exception:
print('Error:', myinstance, 'not found!')
if not inst.state == 'running':
print('Starting', myinstance)
inst.start()
else:
print(myinstance, 'already running or starting up!')

You can not do this.
The EC2 instance does not have a public DNS address assigned until after it is started up. IPv4 addresses are a scarce commodity, so AWS does not permanently assign them. If you stop and start an instance, you may well get a different IPv4 address. Since the AWS public DNS name is based on the IPv4 address, instances do not necessarily retain the same public DNS name when stopped and then started.
I would suggest instead assigning a meaningful tag to your instances that allow you to functionally accomplish what you are trying to accomplish by using the public DNS name.

Related

I want to lock account not using IP Address. Laravel

Laravel has an account lock function.
But it is based on IP address.
It can also be disguised.
Therefore, I want to lock the account itself regardless of the difference in IP address
How can I do?
I made a package for this :)
You can block users, emails, ip addresses, domain names, cities, states, countries, continents, and regions from using your application, logging in, or registering.
https://github.com/jeremykenedy/laravel-blocker
Throttling is not locking so even if you changed it to not be bound to the IP the account will be able to log in again after waiting for some time.
If this is what you want to do then you can override the throttleKey function to use a key not based on IP. If you want to completely ban someone then you can also probably override the decayMinutes to a value of say 100 years.
For example in your normal auth controller:
class class LoginController extends Controller {
use AuthenticatesUsers;
// ...
public $decayMinutes = 52560000; // 100 years
protected function throttleKey(Request $request)
{
return Str::lower($request->input($this->username())); // No IP here now
}
}
Note: Since the rate limiter stores the values in the cache, then clearing the cache will also clear the blocked users. If you want a more permanent solution you can probably add a flag on the user entry in the database indicating that the user is blocked. This is just a quick and dirty solution to get things working for you quickly.
As another note: Not blocking by IP means you're locking someone out if someone else tries to hack into their account. This might be a bit infuriating for your users, which is also something to consider.

Sharing connection pools between client instances in finagle

Given two or more finagle clients that have different destination names, if those names happen to resolve to the same inet address how to I get finagle to only maintain a single pool of connections to that endpoint?
Overly Simple Sample Code
The below code registers a very simple (and mostly useless) Resolver that always resolves to the same address. In practice this would be more like a many to one relationship (instead of all to one). There's another simple application that starts a server and two clients that both use the resolver to find the address to talk to the server.
// Registered with finagle Resolver via META-INF/services
class SmartResolver extends AbstractResolver {
#Override public String scheme() { return "smart"; }
#Override public Var<Addr> bind(String arg) {
return Vars.newConstVar(Addrs.newBoundAddr(Addresses.newInetAddress(
// assume this is more complicated and maps many names to
// one address
new InetSocketAddress("127.0.0.1", 9000)))));
}
}
class Main {
public static void main(String[] args) {
// Create a server, we record stats so we can see how many connections
// there are
InMemoryStatsReceiver stats = new InMemoryStatsReceiver();
ListeningServer server = Thrift.server()
.withStatsReceiver(stats)
.serveIface(":9000", (EchoService.ServiceIface) Future::value);
// create a few clients that all connect to a resolved server, the
// resolver ensures that they all are communicating with our server
EchoService.ServiceIface c1 = Thrift.client()
.newIface("smart!c1", EchoService.ServiceIface.class);
EchoService.ServiceIface c2 = Thrift.client()
.newIface("smart!c2", EchoService.ServiceIface.class);
// make sure any lazy connections have been opened
Await.result(c1.echo("c1"));
Await.result(c2.echo("c2"));
// I'm not sure how to see how many physical connections there are
// incoming to the server, or if it's possible to do this.
assertEquals(1, stats.counter(JavaConversions.asScalaBuffer(Arrays.asList("connects"))))
Await.result(server.close());
}
}
// echo.thrift
service EchoService {
string echo(1: string quack);
}
All the details
Where I work we have a microservice architecture using finagle and thrift, we use Consul for service discovery. Some of the external systems we interact with are very restrictive about the number and frequency of tcp connections they accept, for this reason some service instances are 'assigned responsibility' for these connections. To make sure that requests that need to use specific connections are sent to the correct service, that service registers a new service name in consul representing the connection it is responsible for. Clients then lookup the service by the connection name instead of the service name.
To make that clearer: Say you have a device-service that opens TCP connections to a configured list of devices, the devices only support a single connection at a time. You might have a few instances of this device-service with some scheme in place to divide the devices between the device-service instances. So instance A connects to devices foo and bar, instance B connects to baz.
You now have another service, say poke-service that needs to talk to specific devices (via the device-service). The way I've solved this issue is to have the device-service instance A register foo and bar, and instance B register baz, all against their own local address. So looking up foo resolves to the address for device-service instance A instead of the more generic cluster of all device-service instances.
The problem I'd like to solve is an optimisation problem, I'd like finagle to recognise that both foo and bar actually resolve to the same address and to reuse all the resources that it allocates and maintains as part of the connection. Additionally if foo and bar get re-assigned to different device-service instances, I'd like everything to just work based on the information in Consul which would reflect this change.

how to resolve ip route in ruby

Say a multi-horned PC has two network interface with IP address 192.168.1.100/24 and 192.168.2.100/24. If any other PC send a multicast message to any of them, I need to send a response back, but in the UDP data part of the response, I need to tell that PC my proper IP address which they can reach.
Say 192.168.1.123 send that multicast message, I can use ip route get to 192.168.1.123 to determine which one is the proper interface to use(which is 192.168.1.100), but I don't know how to do this in ruby code.
To invoke external process then parse the stdout is not what I want, cause it's too slow for a busy network, and to make it cross-platform is not that easy.
Currently I mimic the route resolving with these codes:
localifs = Socket.ip_address_list.keep_if { |addr| addr.ipv4? and not(addr.ipv4_loopback?) }
raise Error, "There is no alive ipv4 interface on local machine" if localifs.empty?
src_addr_i = IPAddr.new(src_addr).to_i
localifs = localifs.sort do |x,y|
(IPAddr.new(x.ip_address).to_i ^ src_addr_i) <=> (IPAddr.new(y.ip_address).to_i ^ src_addr_i)
end
host = localifs.first.ip_address

AKKA Remoting lookup remote actors fails when hostname is used

I have been using the AKKA remoting feature. It has been working very well except for one issue. If I try to lookup a remote actor based on its hostname, the lookup fails. However, if I do it based on IP address it works fine. Is there any way to make it work uniformly for both hostname and IP address ?
My application.conf is something like below:
akka {
version = "2.0.2"
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
netty {
...
use-passive-connections = off
hostname = ""
port = 8000
...
}
...
}
}
From another machine:
actorSystem.actorFor("akka://MyActorSystem#10.0.0.1:8000/user/MyActor") //**Works**
actorSystem.actorFor("akka://MyActorSystem#hostname.abc.com:8000/user/MyActor") //**Fails**
I have seen this behavior as well. I expected the Akka actor system to pick up the system host name from java.net.InetAddress.getLocalHost.getHostName.
However this does not always seem to work. On the upside, adding the hostname to your application.conf file should produce the correct result, allowing remote connections looked up via context.actorFor("akka://host.domain.com:8000/user/whatever").
Even when the InetAddress call above produces the desired host name string, e.g. as easily checked in the Scala REPL, Akka seems to prefer binding to the IP Address. If you want Akka to bind to the alias automatically on system start you might consider modifying your Config object (set akka.remote.netty.hostname) before passing it to ActorSystem.apply.
Of course the other, perhaps less desirable, option is to simply set the value on each of your deployed nodes.
Hope that helps!

Amazon EC2 PublicDnsName

How to get PublicDnsName in amazonEC2?
we can get it from instance using ins.getPublicDnsName() but it get created after a certain time,is there any alternative way to get it?
Or some how get it as soon as it is generated?
for making it wait i did
while(flag) {
time = System.currentTimeMillis() - start;
for (Reservation res : ec2.describeInstances().getReservations()) {
for (Instance ins : res.getInstances()) {
if(ins.getState().getName().equalsIgnoreCase("running") || time == MAX_TIME_FOR_THREAD){
System.out.println(ins.getPublicDnsName()+"#########"+ins.getInstanceId());
flag = false;
break;
}
}
}
}
but inside a run of thread but while I am creating multiple ec2 resources it is returning dns of first up machine multiple times where as i feel it should return different dns address.
There is always a slight delay between the instance transitioning to the 'Running' state and the public IP address (and therefore the public DNS name) being allocated - and a longer one if you're also automatically allocating an Elastic IP. It can vary from a second or two up to 5-10 seconds on a busy cluster.
There's nothing you can do but introduce a short delay after detecting the 'Running' state before querying the API - although in your code you're not actually waiting long enough for the instance to get to 'Running' and just hitting MAX_TIME_FOR_THREAD, which is interestingly returning the last DNS name retrieved. This might actually be a small glitch in the API you're using.
In my launcher (written against the .NET API) I have a multithreaded staging loop which launches the instances, then a sleep wait for each to register as 'Running', and then a further sleep wait for the IP address to populate.

Resources