IP Restriction
You protect your ALB / instance using security groups, which whitelist only the CloudFront IP addresses. This list changes regularly, but AWS have the CloudFront Update Security Group Lambda, which helps you keep the list of IPs up to date. It doesn't do initial population of IPs though.
I'm not entirely sure the best way to do the initial security group IP population. You have to have to get the AWS IP list and extract CloudFront IPs out of it, which This script may be useful for. This seems like a problem someone should have solved already, so some searching may find a solution. MLu might know, he'll probably comment in the next day or two.
I usually use NACLs to allow only the ports / protocols through into the subnet with the ALB, then security groups for CloudFront IPs. Don't forget to whitelist any administration required from public IPs, though best practice is to use a bastion host for public access.
WAF
AWS WAF, or another WAF, can protect against application layer attacks. They can also mitigate DDOS attacks.
Other
As you pointed out in the comments, an attacker can create their own CF distribution which means they can attack the server directly. CloudFront / Shield will still apply DDOS protection, which mitigates that somewhat.
Security has to be in layers. You need a secure, scalable application layer in addition to the CDN / WAF. You can rate limit at the application layer, use on-instance firewalls, IDS / IPS.
There's a host of things you can do to make it more difficult for an attacker. If you're online, you're vulnerable to attacks. This is why secure offsite backups and a rehearsed recovery plan are also important.